检测长按UINavigationItem后退按钮

时间:2011-06-28 15:41:58

标签: objective-c ios uinavigationcontroller uinavigationbar uigesturerecognizer

我希望通过基于UINavigationController的应用程序为我的后退按钮添加功能,其中长按后退按钮将弹出到root。但是,我无法弄清楚手势识别器的附加位置。我是否将UINavigationBar子类化并尝试检测长按是否在左按钮区域?

我之前听说有人添加类似的功能。有人有什么想法吗?

4 个答案:

答案 0 :(得分:18)

我知道这个问题已经过时了,但我想出了一个解决方案。我没有尝试将手势识别器添加到按钮本身(这是理想的),而是将其添加到self.navigationController.navigationBar,然后在操作方法中,使用locationInView查看我是否结束后退按钮。我并不完全确定如何准确识别后退按钮,所以我笨拙地抓住第一个子视图,x坐标小于某个任意值,但看起来很有希望。如果有人有更好的方法来识别后退按钮的框架,请告诉我。

- (void)longPress:(UILongPressGestureRecognizer *)sender 
{
    if (sender.state == UIGestureRecognizerStateEnded)
    {
        // set a default rectangle in case we don't find the back button for some reason

        CGRect rect = CGRectMake(0, 0, 100, 40);

        // iterate through the subviews looking for something that looks like it might be the right location to be the back button

        for (UIView *subview in self.navigationController.navigationBar.subviews)
        {
            if (subview.frame.origin.x < 30) 
            {
                rect = subview.frame;
                break;
            }
        }

        // ok, let's get the point of the long press

        CGPoint longPressPoint = [sender locationInView:self.navigationController.navigationBar];

        // if the long press point in the rectangle then do whatever

        if (CGRectContainsPoint(rect, longPressPoint))
            [self doWhatever];
    }
}

- (void)addLongPressGesture
{
    if (NSClassFromString(@"UILongPressGestureRecognizer"))
    {
        UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];
        [self.navigationController.navigationBar addGestureRecognizer:longPress];
        [longPress release];
    }
}

答案 1 :(得分:6)

我相信UIGestureRecognizers只能添加到UIViews和UIViews的子类中。

http://developer.apple.com/library/ios/#documentation/uikit/reference/UIView_Class/UIView/UIView.html

后退按钮是一个来自NSObject的UIBarButtonItem。因此,您将无法使用

将手势识别器附加到标准后退按钮
UILongPressGestureRecognizer *longPressGesture =
            [[[UILongPressGestureRecognizer alloc]
              initWithTarget:self action:@selector(longPress:)] autorelease];

[self.navigationItem.backBarButtonItem addGestureRecognizer:longPressGesture];

但是,您可以向UIBarButtonItem添加自定义视图。自定义视图可以很容易地成为UIView,UIButton,UILabel等。

示例:

UIView *myTransparentGestureView = [[UIView alloc] initWithFrame:CGRectMake(0,0,40,30)];
[myTransparentGestureView addGestureRecognizer:longPressGesture];
[self.navigationItem.backBarButtonItem setCustomView:myTransparentGestureView];
// Or you could set it like this
// self.navigationItem.backBarButtonItem.customView = myTransparentGestureView;
[myTransparentGestureView release];

但是,您必须小心,因为backBarButtonItem上的设置属性适用于您推送的下一个视图。因此,如果您有视图A推送查看B并且您希望在视图B中点击时识别手势。您必须在视图A中进行设置。

答案 2 :(得分:3)

我沿着一条略有不同的道路走,我觉得我会分享它。上面的答案很好,但实际上,如果长按在导航栏的前1/3处,这对我来说已经足够了:

- (void)longPress:(UILongPressGestureRecognizer *)gr
{
    NSLog(@"longPress:");
    UINavigationBar *navBar = [self navigationBar];
    CGFloat height = navBar.bounds.size.height;
    CGPoint pt = [gr locationOfTouch:0 inView:navBar];
    //NSLog(@"PT=%@ height=%f", NSStringFromCGPoint(pt), height);
    if(CGRectContainsPoint(CGRectMake(0,0,100,height), pt)) {
        [self popToViewController:self.viewControllers[0] animated:YES];
    }
}

答案 3 :(得分:1)

这是我的解决方案:

在appDelegate(我的应用中导航栏的&#34;所有者&#34;)中,在applicationDidFinishLaunchingWithOptions中:

获取导航栏视图并将手势识别器添加到整个视图中:

// Get the nav bar view
UINavigationBar *myNavBar = nil;
for (UIView *view in [self.window.rootViewController.view subviews]) {
    if ([view isKindOfClass:[UINavigationBar class]]) {
        NSLog(@"Found Nav Bar!!!");
        myNavBar = (UINavigationBar *)view;
    }
}

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self
                                                                                        action:@selector(backButtonLongPress:)];
[myNavBar addGestureRecognizer:longPress];
NSLog(@"Gesture Recognizer Added.");

然后在appDelegate中,在 - (void)backButtonLongPress:(id)sender

检查手势是否出现在后退按钮的框架内:

if ([sender state] == UIGestureRecognizerStateBegan) {

    // Get the nav bar view
    UINavigationBar *myNavBar = nil;
    for (UIView *view in [self.window.rootViewController.view subviews]) {
        if ([view isKindOfClass:[UINavigationBar class]]) {
            NSLog(@"Found Nav Bar!!!");
            myNavBar = (UINavigationBar *)view;
        }
    }

    // Get the back button view
    UIView *backButtonView = nil;
    for (UIView *view in [myNavBar subviews]) {
        if ([[[view class] description] isEqualToString:@"UINavigationItemButtonView"]) {
            backButtonView = view;
            NSLog(@"Found It: %@", backButtonView);
            NSLog(@"Back Button View Frame: %f, %f; %f, %f", backButtonView.frame.origin.x, backButtonView.frame.origin.y, backButtonView.frame.size.width, backButtonView.frame.size.height);
        }
    }

    CGPoint longPressPoint = [sender locationInView:myNavBar];
    NSLog(@"Touch is in back button: %@", CGRectContainsPoint(backButtonView.frame, longPressPoint) ? @"YES" : @"NO");
    if (CGRectContainsPoint(backButtonView.frame, longPressPoint)) {
        // Place your action here
    }

    // Do nothing if outside the back button frame

}