Ich habe eine benutzerdefinierte Ansicht in einem UIBarButtonItem
, die durch Aufrufen festgelegt wurde -initWithCustomView
. Mein Balkenschaltflächenelement wird einwandfrei wiedergegeben, aber wenn ich darauf tippe, wird die Aktion für mein Zielobjekt nicht aufgerufen.
Hier ist mein Code:
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
quelle
quelle
UIBarButtonItem
erbt vonUIBarItem
undNSObject
weiß daher nichts über Berührungen. Es wäre schön, wenn in den Dokumenten erwähnt würde, dass die Eigenschaftenaction
undtarget
nur gelten, wenn die benutzerdefinierte Ansicht ein UIButton ist.Ich hatte das gleiche Problem, war aber abgeneigt, eine
UIButton
anstelle einer benutzerdefinierten Ansicht für meine zu verwendenUIBarButtonItem
(gemäß der Antwort von Drawonward).Alternativ können Sie
UIGestureRecognizer
der benutzerdefinierten Ansicht ein hinzufügen , bevor Sie sie zum Initialisieren verwendenUIBarButtonItem
. Dies scheint in meinem Projekt zu funktionieren.So würde ich Ihren ursprünglichen Code ändern:
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];
quelle
So mache ich es:
UIButton* infoButton = [UIButton buttonWithType: UIButtonTypeInfoLight]; [infoButton addTarget:self action:@selector(displayAboutUs) forControlEvents:UIControlEventTouchDown]; UIBarButtonItem* itemAboutUs =[[UIBarButtonItem alloc]initWithCustomView:infoButton]; …
quelle
So habe ich den UIButton im UIBarButtonItem implementiert:
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];
quelle
Ich hatte ein ähnliches Problem. Ich folgte zunächst dem von @drawnonward vorgeschlagenen Pfad, geriet dann jedoch in Schwierigkeiten, als ich versuchte, meine Aktion als Popover-Controller auf einem iPad anzuzeigen: Die Verwendung eines eingebetteten UIButton als benutzerdefinierte Ansicht bedeutet, dass der UIButton der Absender des Ereignisses ist, und Die Methode presentPopoverFromBarButtonItem: des Popover-Controllers stürzt ab, wenn versucht wird, Nachrichten zu senden, die nur für tatsächliche UIBarButtonItems geeignet sind.
Die Lösung, die ich schließlich fand, bestand darin, das Bild, das ich verwenden wollte (das "Info" -Symbol), von einem Wegwerf-UIButton zu stehlen und mein UIBarButtonItem wie folgt zu erstellen:
// 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];
Die Verwendung dieses Initialisierers ergibt eine Balkenschaltfläche, deren Ziel und Auswahl tatsächlich funktionieren. Es ist auch einfacher als das Bild in eine benutzerdefinierte Ansicht zu verpacken, aber das ist nur ein Sahnehäubchen.
quelle
Jacob, alles sieht gut aus, aber Sie haben möglicherweise nicht den richtigen Selektor bereitgestellt.
Können Sie überprüfen, ob Ihre Aktion tatsächlich deklariert ist?
- (void) deselectAll;
und nicht
- (void) deselectAll:(id)sender;
Wenn es das letztere ist, müssen Sie die Aktion auf einstellen
@selector(deselectAll:)
. (Beachten Sie das Semikolon, das mit der Methodendeklaration übereinstimmt.)Möglicherweise ist dies auch nichtig
IBAction
, aber das ist für dieses Problem, das Sie haben, nicht relevant.quelle
deselectAll
nicht angerufen wird? Wenn Sie einen Debugger-Haltepunkt festlegen, oder sehen Sie die erwarteten Ergebnisse einfach nicht?Swift 3. Ich hatte ein ähnliches Problem, bei dem ich eine benutzerdefinierte Ansicht innerhalb des Balkenschaltflächenelements hatte. Damit der Wasserhahn funktioniert, habe ich der Ansicht eine Geste zugewiesen und die Aktion festgelegt. Die Ansicht musste eine Steckdose sein, um sie zuzuweisen. Dabei funktionierte es mit der benutzerdefinierten Ansicht.
Festlegen der Geste als Klassenvariable
@IBOutlet weak var incidentView: UIView! let incidentTap = UITapGestureRecognizer()
In viewDidLoad
incidentTap.addTarget(self, action: #selector(self.changeIncidentBarItem)) incidentView.addGestureRecognizer(incidentTap)
quelle
Wenn Sie sich nicht mit einem UIImage zufrieden geben möchten und eine benutzerdefinierte Ansicht in Ihrem Barbuttonitem haben möchten, setzen Sie einen Tippgestenerkenner auf die Eigenschaft customview Ihres Barbuttonitems
let tap = UITapGestureRecognizer(target: self, action: #selector(goProButtonPressed)) deviceStatusBarButtonItem.customView?.addGestureRecognizer(tap)
quelle
Swift 3 : Nachfolgend finden Sie meine vollständige Implementierung für die Anpassung von Schaltflächen und die Ereignisbehandlung.
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 }
Hoffe das hilft
quelle
Isst Ihre benutzerdefinierte Ansicht Berührungsereignisse oder gibt sie diese an die übergeordnete Ansicht weiter?
quelle
UIImageView
. Es isst also keine Ereignisse, nein.Um die Arbeit zu vereinfachen, habe ich auf UIBarButtonItem eine Kategorie erstellt, die folgendermaßen aussieht:
@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
Verwenden Sie in Ihrem Client-Code einfach:
myBarButtonItem.buttonImage = [UIImage imagedNamed:@"image_name"];
Auf diese Weise können Sie Ihre Ziele und Aktionen weiterhin in IB verknüpfen (es ist eine gute Sache, so viel UI-Konfiguration wie möglich in IB zu übertragen).
quelle