UIButton взаимодействие внутри UIPageViewController - PullRequest
12 голосов
/ 07 ноября 2011

Я использую UIPageViewController в своем приложении, и я хотел, чтобы в нем было несколько кнопок UIB, что-то вроде меню. У меня проблема в том, что, когда я помещаю UIB-кнопку (или любой другой интерактивный элемент) рядом с краями экрана и нажимаю на нее, вместо применяемого действия UIButton, происходит то, что страница меняется (потому что нажатие на краю экрана меняет страницу на UIPageViewController). Я хотел бы знать, есть ли способ сделать так, чтобы UIButton имел более высокий приоритет, чем UIPageViewController, чтобы при нажатии на кнопку он применял соответствующее действие вместо изменения страницы.

Ответы [ 8 ]

7 голосов
/ 16 февраля 2012

Я пришел сюда с той же проблемой. ссылка в Split имеет ответ.

Сделайте ваш корневой контроллер представления делегатом каждого из UIPageViewController распознавателей жестов, а затем предотвратите доставку прикосновений, если они происходят внутри любого UIControl:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    return ([touch.view isKindOfClass:[UIControl class]] == NO);
}
4 голосов
/ 08 ноября 2011

UIPageViewController имеет два UIGestureRecognizer.Вы можете получить к ним доступ через свойство gestRecognizers.Определите, какой из них является UITapGestureRecognizer, а затем используйте this. Надеюсь, это поможет.

2 голосов
/ 13 сентября 2012

Для людей, которые просто хотят скопировать / вставить код, вот мое:

// I don't want the tap on borders to change the page
-(void) desactivatePageChangerGesture {
     for (UIGestureRecognizer* gestureRecognizer in self.pageViewController.gestureRecognizers) {
        if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
            gestureRecognizer.enabled = NO;
        }
    }
}

Просто вызовите эту функцию после создания UIPageViewController.

1 голос
/ 12 апреля 2012

У меня была такая же проблема, и я не был уверен, как обработать методы делегата UIGestureRecognizer. Этот короткий пример предполагает, что вы используете тип проекта «Приложение на основе страницы» в Xcode 4. Вот что я сделал:

  • В RootViewController.h я объявил, что RootViewController будет обрабатывать протокол UIGestureRecognizerDelegate:

    @interface RootViewController : UIViewController <UIPageViewControllerDelegate, UIGestureRecognizerDelegate>
    
  • В RootViewController.m я назначил RootViewController в качестве делегата для UITapGestureRecognizer. Это делается в конце метода viewDidLoad. Я сделал это, перебирая каждый gestRecognizer, чтобы увидеть, какой из них был UITapGestureRecognizer.

    NSEnumerator *gestureLoop = [self.view.gestureRecognizers objectEnumerator];
    id gestureRecognizer;
    while (gestureRecognizer = [gestureLoop nextObject]) {
        if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
            [(UITapGestureRecognizer *)gestureRecognizer setDelegate:self];
        }
    }
    
  • Наконец, я добавил метод gestRecognizer: shouldReceiveTouch в конец RootViewController.m (это скопировано непосредственно из ссылки Сплита):

    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
        if ([touch.view isKindOfClass:[UIControl class]]) {
            // we touched a button, slider, or other UIControl
            return NO; // ignore the touch
        }
        return YES; // handle the touch
    }
    
1 голос
/ 15 февраля 2012

Закомментируйте эти строки из своего кода

self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;

или используйте UIGestureRecognizer, как говорит Сплит

Надеюсь, это поможет вам

0 голосов
/ 13 марта 2019

Ответ Swift 5 здесь должен сделать работу.

pageViewController.view.subviews.compactMap({ $0 as? UIScrollView }).first?.delaysContentTouches = false

0 голосов
/ 23 октября 2015

Ни одно из решений здесь, где вы перехватываете распознаватели жестов касания UIPageViewController, не работало для меня. Я нацелился на iOS 8 и 9.

Что сработало, так это переопределение функций touchesBegan, touchesCancelled, touchesMoved и touchesEnded в моей пользовательской кнопке, которая является подклассом UIControl. Затем я просто вручную отправляю событие управления .TouchUpInside, если касание началось и закончилось в рамке моей пользовательской кнопки.

Мне не нужно было делать ничего особенного для содержащего контроллер представления страницы или контроллера представления, который содержит контроллер представления страницы.

0 голосов
/ 02 декабря 2014

СТАРЫЙ ОТВЕТ: Если ваш UIPageViewController имеет transitionStyle из UIPageViewControllerTransitionStyleScroll, и вы используете iOS 6.0+, то вы не можете использовать метод gestureRecognizer:shouldReceiveTouch:, потому что нетспособ установить делегата на self на gestureRecognizers, так как pageViewController.gestureRecognizers вернет ноль.См. UIPageViewController не возвращает распознаватели жестов в iOS 6 для получения дополнительной информации об этом.

Если вы просто хотите убедиться, что ваш UIPageViewController передает события касания кнопки в UIButton, вы можете использовать

for (UIScrollView *view in _pageViewController.view.subviews) {
    if ([view isKindOfClass:[UIScrollView class]]) {
        view.delaysContentTouches = NO;
    }
}

, если у вас transitionStyle из UIPageViewControllerTransitionStyleScroll и вы используете iOS 6.0 +.

См. этот ответ о том, почему delaysContentTouches = NO требуетсядля некоторых случаев UIButton в UIScrollView

ОБНОВЛЕНИЕ: После небольшого исследования выясняется, что если ваша проблема заключается в том, что щелчок UIButton кажется тольконазывается иногда , тогда это, вероятно, на самом деле желаемое поведение внутри UIScrollView.UIScrollView использует свойство delaysContentTouches , чтобы автоматически определять, пытался ли пользователь прокрутить или пытался нажать кнопку в представлении прокрутки.Я бы предположил, что лучше не изменять это поведение по умолчанию на NO, так как это приведет к невозможности прокрутки, если палец пользователя находится над кнопкой.

...