How can you add a UIGestureRecognizer to a UIBarButtonItem as in the common undo/redo UIPopoverController scheme on iPad apps?

后端 未结 15 1632
被撕碎了的回忆
被撕碎了的回忆 2020-12-07 12:36

Problem

In my iPad app, I cannot attach a popover to a button bar item only after press-and-hold events. But this seems to be standard for

15条回答
  •  北荒
    北荒 (楼主)
    2020-12-07 12:57

    I tried something similar to what Ben suggested. I created a custom view with a UIButton and used that as the customView for the UIBarButtonItem. There were a couple of things I didn't like about this approach:

    • The button needed to be styled to not stick out like a sore thumb on the UIToolBar
    • With a UILongPressGestureRecognizer I didn't seem to get the click event for "Touch up Inside" (This could/is most likely be programing error on my part.)

    Instead I settled for something hackish at best but it works for me. I'm used XCode 4.2 and I'm using ARC in the code below. I created a new UIViewController subclass called CustomBarButtonItemView. In the CustomBarButtonItemView.xib file I created a UIToolBar and added a single UIBarButtonItem to the toolbar. I then shrunk the toolbar to almost the width of the button. I then connected the File's Owner view property to the UIToolBar.

    Interface Builder view of CustomBarButtonViewController

    Then in my ViewController's viewDidLoad: message I created two UIGestureRecognizers. The first was a UILongPressGestureRecognizer for the click-and-hold and second was UITapGestureRecognizer. I can't seem to properly get the action for the UIBarButtonItem in the view so I fake it with the UITapGestureRecognizer. The UIBarButtonItem does show itself as being clicked and the UITapGestureRecognizer takes care of the action just as if the action and target for the UIBarButtonItem was set.

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib
    
        UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGestured)];
    
        UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(buttonPressed:)];
    
        CustomBarButtomItemView* customBarButtonViewController = [[CustomBarButtomItemView alloc] initWithNibName:@"CustomBarButtonItemView" bundle:nil];
    
        self.barButtonItem.customView = customBarButtonViewController.view;
    
        longPress.minimumPressDuration = 1.0;
    
        [self.barButtonItem.customView addGestureRecognizer:longPress];
        [self.barButtonItem.customView addGestureRecognizer:singleTap];        
    
    }
    
    -(IBAction)buttonPressed:(id)sender{
        NSLog(@"Button Pressed");
    };
    -(void)longPressGestured{
        NSLog(@"Long Press Gestured");
    }
    

    Now when a single click occurs in the ViewController's barButtonItem (Connected via the xib file) the tap gesture calls the buttonPressed: message. If the button is held down longPressGestured is fired.

    For changing the appearance of the UIBarButton I'd suggest making a property for CustomBarButtonItemView to allow access to the Custom BarButton and store it in the ViewController class. When the longPressGestured message is sent you can change the system icon of the button.

    One gotcha I've found is the customview property takes the view as is. If you alter the custom UIBarButtonitem from the CustomBarButtonItemView.xib to change the label to @"really long string" for example the button will resize itself but only the left most part of the button shown is in the view being watched by the UIGestuerRecognizer instances.

提交回复
热议问题