обнаружить долгое нажатие на кнопку назад UINavigationItem - PullRequest
14 голосов
/ 28 июня 2011

Я хочу добавить функциональность кнопкам «Назад» через приложение на основе UINavigationController, в котором долгое нажатие кнопки «Назад» приведет к появлению в корневом каталоге.Тем не менее, я не могу понять, где установить распознаватель жестов.Должен ли я создать подкласс UINavigationBar и попытаться определить, находится ли длительное нажатие в области левой кнопки?

Я уже слышал о людях, добавляющих аналогичные функции ранее.У кого-нибудь есть идеи?

Ответы [ 4 ]

18 голосов
/ 04 апреля 2012

Я знаю, что этот вопрос старый, но я нашел решение.Вместо того, чтобы пытаться добавить распознаватель жестов к самой кнопке (что было бы идеально), я добавил его к self.navigationController.navigationBar, а затем в методе действия с помощью locationInView проверил, нахожусь ли я над кнопкой возврата.Я не был полностью уверен в том, как точно определить кнопку «назад», поэтому я неуклюже просто захватывал первое подпредставление с координатой х, меньшей некоторого произвольного значения, но это кажется многообещающим.Если у кого-то есть лучший способ определить рамку кнопки «назад», дайте мне знать.

- (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];
    }
}
6 голосов
/ 29 июня 2011

Я считаю, что UIGestureRecognizer могут быть добавлены только в UIViews и подклассы UIViews.

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

Кнопка "Назад" - это UIBarButtonItem, который происходит от NSObject. Следовательно, вы не сможете прикрепить распознаватель жестов к стандартной кнопке возврата, используя

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.

3 голосов
/ 24 октября 2013

Я пошел немного по другому пути, подумал, что поделюсь им. Приведенные выше ответы хороши, но на самом деле, если долгое нажатие находится в первой трети навигационной панели, этого достаточно для меня:

- (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];
    }
}
1 голос
/ 03 октября 2016

Вот мое решение:

В 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) отправитель

Проверьте, происходит ли жест в рамке кнопки «назад»:

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

}
...