Непрерывная прокрутка между UIPanGestureRecognizer и повторно включенным UIScrollView

У меня есть UIScrollView с поддержкой пейджинга, и я добавил к нему свой собственный UIPanGestureRegonizer. В некоторых случаях мой контроллер просмотра установит scrollview.scrollEnabled = NO, а затем добавит к нему признак распознавания панорамы (я не использую собственный распознаватель scrollview).

Итак, прокрутка отключена, но я жду, когда пользователь коснется моего распознавателя жестов. Когда он распознает, он вызывает свое действие, в котором я снова включаю прокрутку.

Проблема заключается в том, что пока пользователь по-прежнему имеет палец вниз, мой scrollview не отслеживает пальцем. Он не запускает прокрутку до тех пор, пока палец не будет поднят, а затем снова перетащит. Таким образом, мой распознаватель жестов поглощает все касания и не перенаправляет их на прокрутку.

Я попытался переключиться на panGestureRecognizer.cancelsTouchesInView = NO;, но он, похоже, не имеет никакого эффекта (я в настоящее время удаляю этот распознаватель, как только я снова включаю прокрутку, но могу ли я сделать это или нет, не решает мою проблему). Я также изучил свойства delays... UIGestureRecognizer, но они также не помогают.

Любые идеи? Как я могу заставить эти события продолжать переходить к моему просмотру прокрутки?

Ответ 1

Ответ немного проще, если вы ориентируетесь только на iOS 5 и выше, потому что в этом случае вам действительно нужно повторно использовать свойство UIScrollView panGestureRecognizer.

В любом случае ключевым шагом является НЕ повторно использовать scrollEnabled, но вместо этого в подкласс UIScrollView создайте собственное свойство для управления этим состоянием и переопределите setContentOffset:.

    - (void) setContentOffset:(CGPoint)contentOffset
    {
        if(self.programaticScrollEnabled)
            [super setContentOffset:contentOffset];
    }

Здесь одно возможное решение iOS 4+:

  • Подкласс UIScrollView (или подкласс другого подкласса UIScrollView, в зависимости от ваших потребностей).
  • Переопределите все инициализаторы, чтобы обеспечить, чтобы ваш код установки вызывался.
  • Объявить свойство BOOL и переопределить setContentOffset: как описано выше.
  • В вашем установочном коде настройте UIPanGestureRecognizer и установите свою переменную состояния, чтобы разрешить прокрутку программы (при условии, что вы хотите по умолчанию):

    panRecognizer = [[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)] autorelease];
    //These properties may change according to your needs
    panRecognizer.cancelsTouchesInView = NO;
    panRecognizer.delaysTouchesBegan = NO;
    panRecognizer.delaysTouchesEnded = NO;
    [self addGestureRecognizer:panRecognizer];
    panRecognizer.delegate = self;
    
    self.programaticScrollEnabled = YES;
    
  • Управлять тем, какие жесты могут возникать одновременно. В моем случае:

    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
    {
        return YES;
    }
    
  • Поверните программную прокрутку туда, где вам это нужно. Например:

    - (void)handleGesture:(UIPanGestureRecognizer *)gestureRecognizer
    {
        self.programaticScrollEnabled = YES;
    }
    
    - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
    {
        self.programaticScrollEnabled = YES;
        return YES;
    }