Как распознать жест смахивания в UIScrollView

Я пытаюсь распознать жест смахивания влево/вправо в UIScrollView. Я пытался создать UISwipeGestureRecognizers и связать их с представлением прокрутки. Работает, но очень редко. Чаще всего мне не звонят. Почему?

Как я могу надежно заставить работать свайп влево/вправо? Могу ли я использовать распознаватели жестов или мне нужно как-то самому с этим справиться в touchesBegan/Ended

Спасибо


person David    schedule 06.09.2010    source источник


Ответы (4)


Догадаться. В моем случае мой UIScrollView содержал UIImage, масштабирование которого я разрешил. По-видимому, это означало, что прокрутка включена, и у UIScrollView возникли проблемы с различением жестов, предназначенных для прокрутки, и смахивания (следующее, предыдущее изображение).

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

Критическая часть заключается в том, чтобы поместить следующее в делегат представления прокрутки:

- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
  if (scrollView.zoomScale!=1.0) {
    // Zooming, enable scrolling
    scrollView.scrollEnabled = TRUE;
  } else {
    // Not zoomed, disable scrolling so gestures get used instead
    scrollView.scrollEnabled = FALSE;
  }
}

Я также должен инициализировать вид прокрутки с отключенной прокруткой. Чтобы включить масштабирование, просто предоставьте изображение при вызове делегата,

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
  // Return the scroll view
  return myImage;
}

И установите несколько параметров в viewDidLoad для масштабирования и настройки распознавателей жестов.

- (void)viewDidLoad {
  [super viewDidLoad];
  myScrollView.contentSize = CGSizeMake(myImage.frame.size.width, myImage.frame.size.height);
  myScrollView.maximumZoomScale = 4.0;
  myScrollView.minimumZoomScale = 1.0;
  myScrollView.clipsToBounds = YES;
  myScrollView.delegate = self;

  [myScrollView addSubview:myImage];
  [self setWantsFullScreenLayout:TRUE];

  myScrollView.scrollEnabled = FALSE; 
  UISwipeGestureRecognizer *recognizer = 
    [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:)];
  recognizer.delaysTouchesBegan = TRUE;
  [myScrollView addGestureRecognizer:recognizer];
  [recognizer release];

  recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeFrom:)];
  recognizer.direction = UISwipeGestureRecognizerDirectionLeft;
  [myScrollView addGestureRecognizer:recognizer];
  [recognizer release];
  [myScrollView delaysContentTouches];
}
person David    schedule 06.09.2010
comment
действительно отличная находка Дэвида. мои распознаватели прокрутки также не сработали. Я сдался и использовал touchesBegan: с NSNotification, но он также дал уведомление для MasterViewControllers (в iPad). У меня были затуманенные глаза при поиске этой проблемы. Вы сэкономили мое время и энергию!! сердечно благодарю Давида. Продолжайте публиковать трюки .. хорошего дня. - person gopikrishnan; 09.12.2010
comment
А может и в одну строку - scrollView.scrollEnabled = (scale != 1.0f) - person Yariv Nissim; 22.02.2013
comment
Спасибо! Я хотел бы сделать небольшое предложение, так как я столкнулся с проблемами в ландшафте. Я обошел эти проблемы, изменив метод scrollViewDidZoom на это: '- (void)scrollViewDidZoom:(UIScrollView *)scrollView { if (scrollView.zoomScale!=self.scrollview.minimumZoomScale) { // Масштабирование, включить прокрутку scrollView.scrollEnabled = TRUE ; } else { // Без масштабирования, отключите прокрутку, чтобы вместо нее использовались жесты scrollView.scrollEnabled = FALSE; } }' - person johnnelm9r; 22.07.2013
comment
Новый ответ ниже с использованием requireGestureRecognizerToFail намного проще. - person Daniel; 16.03.2015

UIScrollView *scrollView = ...
UISwipeGestureRecognizer *mySwipe = ...

Правильное решение этой проблемы — добавить одну строку кода:

[scrollView.panGestureRecognizer requireGestureRecognizerToFail:mySwipe]

Быстрая версия:

scrollView.panGestureRecognizer.requireGestureRecognizerToFail(mySwipe)

Версия Swift4:

scrollView.panGestureRecognizer.require(toFail: mySwipe!);
person Alexander Volkov    schedule 27.01.2015
comment
Абсолютно согласен, что это правильное решение! Я также должен добавить в ту же строку pinchGestureRecognizer, чтобы сделать ее надежной, поскольку я пытался обнаружить смахивание несколькими пальцами. - person Luke Rogers; 24.04.2015
comment
Это определенно кажется правильным путем! Иногда я нахожу, что жест смахивания срабатывает слишком рано, но теперь это проблема обработчика смахивания. По крайней мере, нам не нужно делать всякие странные хакерские вещи, которые предлагают другие люди, и просто чувствовать себя не так. Спасибо!! - person horseshoe7; 14.12.2015
comment
отличный ответ на все времена .. :) - person Ankit Kumar; 11.02.2016
comment
Разве это не нарушает жест панорамирования прокрутки в направлении жеста смахивания? По крайней мере, я не могу заставить жест смахивания потерпеть неудачу. Что, если вам нужна возможность панорамировать увеличенное изображение, а также перемещаться между изображениями? Похоже, принятое решение лучше, хотя оно может быть хакерским. - person nickjwallin; 06.06.2016
comment
@nickjwallin нет. - person Alexander Volkov; 09.06.2016

Хороший пост.

Я делал то же самое (без просмотра изображения), и мне в основном приходилось отключать прокрутку, если размер содержимого был меньше высоты (мой вид прокрутки прокручивается только по вертикали).

if (scrollView.contentSize.height>scrollView.frame.size.height) {
    scrollView.scrollEnabled = YES;
}
else {
    scrollView.scrollEnabled = NO;
}

Это помогло мне

person echappy    schedule 30.09.2010

Для тех, кто хочет анимировать и настроить свои распознаватели жестов.

Мы можем использовать делегаты UIScrollView и UIGestureRecognizer:

 Class ViewController: UIViewController, UISCrollViewDelegate, UIGestureRecognizerDelegate { 


   override func viewDidLoad() {
    super.viewDidLoad()

    scrollView.delegate = self
    swipeLeft.delegate = self
    swipeRight.delegate = self

  }


  func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
    return true
  }

  func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
  }

  func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    return scrollView.alwaysBounceHorizontal
  }


  func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {

    // Your custom animation at the end of scrolling.
  }
}
person Celeste    schedule 18.07.2019