Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/106.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 检测长时间按压UINavigationItem';s后退按钮_Objective C_Ios_Uinavigationcontroller_Uinavigationbar_Uigesturerecognizer - Fatal编程技术网

Objective c 检测长时间按压UINavigationItem';s后退按钮

Objective c 检测长时间按压UINavigationItem';s后退按钮,objective-c,ios,uinavigationcontroller,uinavigationbar,uigesturerecognizer,Objective C,Ios,Uinavigationcontroller,Uinavigationbar,Uigesturerecognizer,我想通过基于UINavigationController的应用程序为我的后退按钮添加功能,长按后退按钮将弹出到root。但是,我不知道在哪里安装手势识别器。我是否要将UINavigationBar子类化,并尝试检测长按是否位于左按钮区域 我以前听说有人添加了类似的功能。有人有什么想法吗?我相信UIGestureRecognitors只能添加到UIView和UIView的子类中 “后退”按钮是从NSObject派生的UIBarButtonim。因此,您将无法使用将手势识别器附加到标准后退按钮 U

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


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

我相信UIGestureRecognitors只能添加到UIView和UIView的子类中

“后退”按钮是从NSObject派生的UIBarButtonim。因此,您将无法使用将手势识别器附加到标准后退按钮

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

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

我知道这个问题很老,但我想出了一个解决方案。我没有尝试将手势识别器添加到按钮本身(这很理想),而是将其添加到
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];
    }
}
-(void)longPress:(uilongpress gesture识别器*)发送方
{
if(sender.state==UIGestureRecognitizerStateEnded)
{
//设置一个默认矩形,以防由于某种原因找不到“后退”按钮
CGRect rect=CGRectMake(0,0,100,40);
//在子视图中迭代,查找看起来可能是返回按钮的正确位置的内容
用于(self.navigationController.navigationBar.subview中的UIView*子视图)
{
if(子视图.frame.origin.x<30)
{
rect=子视图.frame;
打破
}
}
//好吧,让我们来谈谈长篇大论的要点
CGPoint longPressPoint=[发送方位置查看:self.navigationController.navigationBar];
//如果长按点位于矩形中,则执行任何操作
if(CGRectContainsPoint(rect,longPressPoint))
[自我陶醉];
}
}
-(无效)添加长按手势
{
if(NSClassFromString(@“UILongPressGestureRecognitor”))
{
UILongPressGestureRecognizer*longPress=[[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPress:)];
[self.navigationController.navigationBar AddgestureRecognitor:longPress];
[新闻稿];;
}
}

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

在appDelegate(我的应用程序中导航栏的“所有者”)中,在ApplicationIDFinishLaunchingWithOptions中:

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

// 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

}

向backButtomItem上的自定义视图添加手势识别器对我不起作用。。。识别器拒绝开火。您是否能够使用上面的代码使其工作?它可能不工作,因为BackbarButtonim是只读的,因此不接受自定义视图。您很可能需要创建自己的LeftBarbuttonite,如下面的答案所示。啊,但我失去了我的背箭,除非我找到一个图像。。。可能不值得。不过还是要谢谢你!好主意。下次我需要这样做的时候,我会试试你的方法。谢谢你的跟进!只要长按一下就可以弹出,这对我来说是合理的。我有相同的要求,比如在后退按钮上设置长按手势。这种方法的问题是后退按钮不会保持高亮显示状态。因此我将cancelsTouchesInView属性设置为否。但是,我的长按处理程序和backButton处理程序都会显示呼叫。有什么解决方案吗???@user1010819不,没有什么能让我感到惊讶。不过,老实说,如果我今天要解决这个问题,毫无疑问我不会使用这个技巧将长按手势添加到标准导航控制器中(因为最终用户在标准导航栏等标准UI控件上使用自定义行为很容易混淆)。我会用我自己的看起来不同的图形按钮来替换后退按钮(让用户知道在这个应用程序中工作的方式不同),可能会用我自己的自定义容器类来替换整个导航控制器和导航栏。我也做了同样的事情。但使用自定义后退按钮会弄乱交互式弹出手势。在浪费了2-3天之后,我无法找到合适的工作解决方案,因此我继续进行,并找到了解决方法问题的方法。为了防止BackbarButtonim操作处理程序执行,我在中将cancelsTouchesInView设置为YESUILongPressGestureRecognitizerStateEnded。此操作有效。