检测长按 UINavigationItem 的后退按钮

发布于 2024-11-17 16:33:21 字数 159 浏览 1 评论 0原文

我想通过基于 UINavigationController 的应用程序向后退按钮添加功能,长按后退按钮将弹出到根目录。但是,我不知道在哪里附加手势识别器。我是否子类化 UINavigationBar 并尝试检测长按是否位于左侧按钮区域?

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

I want to add functionality to my back buttons through my UINavigationController-based app where long-pressing the back button will pop to root. However, I can't figure out where to attach the gesture recognizer. Do I subclass UINavigationBar and try and detect if the long press is in the left button region?

I've heard of people adding similar functionality before. Anyone have any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

枕梦 2024-11-24 16:33:21

我知道这个问题很老了,但我想出了一个解决方案。我没有尝试将手势识别器添加到按钮本身(这将是理想的),而是将其添加到 self.navigationController.navigationBar ,然后在操作方法中使用 locationInView< /code> 看看我是否超过了后退按钮。我不完全确定如何精确识别后退按钮,所以我笨拙地只是抓住 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];
    }
}

I know this question is old, but I came up with a solution. Instead of trying to add the gesture recognizer to the button itself (which would be ideal), I added it to the self.navigationController.navigationBar and then in the action method, use the locationInView to see if I'm over the back button. I wasn't entirely sure about how to identify the back button precisely, so I'm clumsily just grabbing the the first subview with an x coordinate less than some arbitrary value, but it seems promising. If someone has a better way to identify the frame of the back button, let me know.

- (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];
    }
}
与他有关 2024-11-24 16:33:21

我相信 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 中进行设置。

I believe UIGestureRecognizers can only be added to UIViews and subclasses of UIViews.

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

The back button is a UIBarButtonItem that descends from NSObject. Therefore, you won't be able to attach a gesture recognizer to a standard back button using

UILongPressGestureRecognizer *longPressGesture =
            [[[UILongPressGestureRecognizer alloc]
              initWithTarget:self action:@selector(longPress:)] autorelease];

[self.navigationItem.backBarButtonItem addGestureRecognizer:longPressGesture];

You can however add a custom view to a UIBarButtonItem. A custom view could just as easily be a UIView, UIButton, UILabel, etc.

Example:

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];

You have to be careful however, since setting properties on backBarButtonItem applies to the next view that you push. So if you have view A that pushes to view B and you want the gesture to be recognized when you tap back in view B. You must set it up in view A.

弃爱 2024-11-24 16:33:21

我走了一条稍微不同的路,我想我会分享它。上面的答案很好,但实际上,如果长按位于导航栏的前导 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];
    }
}

I followed a slightly different path, figured I'd share it. The above answers are fine, but really, if the long press is in the leading 1/3 of the nav bar, that's good enough for me:

- (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];
    }
}
泅渡 2024-11-24 16:33:21

这是我的解决方案:

在 appDelegate (我的应用程序中导航栏的“所有者”)中,在 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

}

Here's my solution:

In appDelegate (the "owner" of the nav bar in my app), In applicationDidFinishLaunchingWithOptions:

Get the nav bar view and add the gesture recognizer to the whole view:

// 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.");

Then in appDelegate, in -(void) backButtonLongPress:(id) sender

Check to see if the gesture occurs within the frame of the back button:

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

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文