Mam niestandardowy widok wewnątrz UIBarButtonItem
, ustawiany przez telefon -initWithCustomView
. Mój przycisk paska renderuje się dobrze, ale kiedy go stukam, nie wywołuje akcji na moim obiekcie docelowym.
Oto mój kod:
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"someImage.png"]];
UIBarButtonItem *bbItem = [[UIBarButtonItem alloc] initWithCustomView:imageView];
self.navigationItem.leftBarButtonItem = bbItem;
[imageView release];
[bbItem setTarget:self];
[bbItem setAction:@selector(deselectAll)];
iphone
ios
objective-c
cocoa-touch
Jacob Relkin
źródło
źródło
UIBarButtonItem
Dziedziczy zUIBarItem
aNSObject
więc nie wiem nic o akcentami. Byłoby miło, gdyby dokumentacja wspomniała, że właściwościaction
itarget
mają zastosowanie tylko wtedy, gdy widok niestandardowy to UIButton.Miałem ten sam problem, ale nie chciałem
UIButton
używać widoku niestandardowego zamiast mojegoUIBarButtonItem
(zgodnie z odpowiedzią drawonward).Alternatywnie, możesz dodać
UIGestureRecognizer
do widoku niestandardowego przed użyciem go do inicjalizacjiUIBarButtonItem
; wydaje się, że to działa w moim projekcie.Oto jak zmodyfikowałbym twój oryginalny kod:
UIImageView *SOCImageView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"cancel_wide.png"]]; UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(deselectAll:)]; [SOCImageView addGestureRecognizer:tapGesture]; SOItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:SOCImageView] autorelease]; [tapGesture release]; [SOCImageView release];
źródło
Oto jak to działa:
UIButton* infoButton = [UIButton buttonWithType: UIButtonTypeInfoLight]; [infoButton addTarget:self action:@selector(displayAboutUs) forControlEvents:UIControlEventTouchDown]; UIBarButtonItem* itemAboutUs =[[UIBarButtonItem alloc]initWithCustomView:infoButton]; …
źródło
Oto jak zaimplementowałem UIButton wewnątrz UIBarButtonItem:
UIButton *logoButton = [UIButton buttonWithType:UIButtonTypeCustom]; [logoButton setImage: [UIImage imageNamed:@"icon.png"] forState:UIControlStateNormal]; logoButton.frame = CGRectMake(0, 0, 30, 30); [logoButton addTarget:self action:@selector(showAbout:) forControlEvents:UIControlEventTouchUpInside]; UIBarButtonItem *barItem = [[UIBarButtonItem alloc] initWithCustomView:logoButton]; self.navigationItem.rightBarButtonItem = barItem; [barItem release];
źródło
Miałem podobny problem. Początkowo podążałem ścieżką sugerowaną przez @drawnonward, ale potem wpadłem w kłopoty, gdy próbowałem, aby moja akcja przedstawiała kontroler popover na iPadzie: użycie wbudowanego przycisku UIButton jako widoku niestandardowego oznacza, że UIButton jest nadawcą zdarzenia, i PresentPopoverFromBarButtonItem: metoda kontrolera popover ulega awarii, gdy próbuje wysłać do niej komunikaty, które są odpowiednie tylko dla rzeczywistych elementów UIBarButtonItems.
Ostatecznie znalazłem rozwiązanie polegające na kradzieży obrazu, którego chciałem użyć (ikona „info”) z jednorazowego UIButton i skonstruowanie mojego UIBarButtonItem w następujący sposób:
// Make the info button use the standard icon and hook it up to work UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeInfoLight]; UIBarButtonItem *barButton = [[[UIBarButtonItem alloc] initWithImage:infoButton.currentImage style:UIBarButtonItemStyleBordered target:self action:@selector(showInfo:)] autorelease];
Użycie tego inicjatora daje przycisk paska, którego cel i selektor faktycznie działają. Jest to również łatwiejsze niż zawijanie obrazu w widoku niestandardowym, ale to tylko lukier.
źródło
Jeśli nie chcesz rozliczać się z UIImage i mieć niestandardowy widok w swoim barbuttonitem, ustaw rozpoznawanie gestów dotknięcia na właściwość customview swojego barbuttonitem
let tap = UITapGestureRecognizer(target: self, action: #selector(goProButtonPressed)) deviceStatusBarButtonItem.customView?.addGestureRecognizer(tap)
źródło
Jacob, wszystko wygląda dobrze, ale być może nie podałeś prawidłowego selektora.
Czy możesz sprawdzić, czy Twoje działanie zostało faktycznie zadeklarowane?
- (void) deselectAll;
i nie
- (void) deselectAll:(id)sender;
Jeśli jest to drugie, musisz ustawić akcję na
@selector(deselectAll:)
. (zwróć uwagę na średnik, aby dopasować deklarację metody)Może być też pustka
IBAction
, ale to nie dotyczy tego problemu.źródło
deselectAll
że nie dzwonisz? Ustawiając punkt przerwania debugera, czy po prostu nie widzisz oczekiwanych wyników?Swift 3. Miałem podobny problem, gdy miałem niestandardowy widok wewnątrz elementu przycisku paska. Aby kran działał, przypisałem do widoku gest i ustawiłem akcję. Widok musiał być ujściem, aby go przypisać. W ten sposób działało z widokiem niestandardowym.
Ustawianie gestu jako zmiennej klasy
@IBOutlet weak var incidentView: UIView! let incidentTap = UITapGestureRecognizer()
W widokuDidLoad
incidentTap.addTarget(self, action: #selector(self.changeIncidentBarItem)) incidentView.addGestureRecognizer(incidentTap)
źródło
Swift 3 : Poniżej znajduje się moja pełna implementacja dostosowywania przycisków i obsługi zdarzeń.
override func viewDidLoad() { super.viewDidLoad() let button = UIButton.init(type: .custom) button.setTitle("Tester", for: .normal) button.setTitleColor(.darkGray, for: .normal) button.layer.borderWidth = 1 button.layer.cornerRadius = 5 button.layer.borderColor = UIColor.darkGray.cgColor button.addTarget(self, action: #selector(self.handleButton), for: .touchUpInside) self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button) } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) if let button = self.navigationItem.rightBarButtonItem?.customView { button.frame = CGRect(x:0, y:0, width:80, height:34) } } func handleButton( sender : UIButton ) { // It would be nice is isEnabled worked... sender.alpha = sender.alpha == 1.0 ? 0.5 : 1.0 }
Mam nadzieję że to pomoże
źródło
Czy Twój niestandardowy widok zjada zdarzenia dotykowe, czy przekazuje je do widoku rodzica?
źródło
UIImageView
. Więc to nie zjada żadnych wydarzeń, nie.Aby ułatwić pracę, utworzyłem kategorię na UIBarButtonItem, która wygląda następująco:
@implementation UIBarButtonItem (CustomButtonView) - (void)setButtonImage:(UIImage *)image { UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom]; [button setBackgroundImage:image forState:UIControlStateNormal]; [button sizeToFit]; [button addTarget:self.target action:self.action forControlEvents:UIControlEventTouchUpInside]; self.customView = button; } - (UIImage *)buttonImage { return [(UIButton *)self.customView imageForState:UIControlStateNormal]; } @end
W swoim kodzie klienta po prostu użyj:
myBarButtonItem.buttonImage = [UIImage imagedNamed:@"image_name"];
Zrobione w ten sposób, nadal możesz łączyć cele i akcje w IB (wpychanie jak największej ilości konfiguracji UI do IB jest dobrą rzeczą).
źródło