Как заставить UIScrollView игнорировать отдельные касания?

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

Это можно сделать с помощью [innerScrollView setUserInteractionEnabled:NO], но это, очевидно, также отключает жесты сжатия и панорамирования во внутреннем представлении прокрутки. Есть ли способ сохранить жесты сжатия и панорамирования, обрабатываемые внутренним видом масштабирования, и пересылать все другие события вверх по цепочке респондента?

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


person zoul    schedule 13.06.2012    source источник


Ответы (2)


Что я выяснил: событие с одним касанием в конечном итоге доходит до touchesBegan:withEvent: в представлении содержимого внутри представления внутренней прокрутки. Это представление содержимого не реализует метод, а реализация по умолчанию UIView передает событие вверх по цепочке респондента. Здесь у нас есть представление внутренней прокрутки, которое действительно реализует touchesBegan:withEvent:. Эта реализация проглатывает одиночное нажатие, и по цепочке респондента ничего не поднимается. Что помогло, так это создание подкласса UIScrollView и отправка доработок цепочки респондентов вручную:

- (void) touchesBegan: (NSSet*) touches withEvent: (UIEvent*) event
{
    [[self nextResponder] touchesBegan:touches withEvent:event];
}

Конечно, также хорошо пересылать по крайней мере touchesEnded:withEvent: таким образом. Это делает все, что мне нужно. Представление внутренней прокрутки может обрабатывать масштабирование и панорамирование, представление внешней прокрутки принимает события однократного нажатия. Я могу даже увеличить масштаб, а затем сдвинуть его так далеко вправо, что перехожу на следующую страницу.

person zoul    schedule 13.06.2012
comment
Хороший вопрос и отличный ответ. Я использую это, чтобы добавить UIScrollView внутри UITableViewCell, чтобы имитировать смахивание для действий. Мне нужно было игнорировать события касания в scrollView и перенаправлять их в саму ячейку, чтобы сохранить выбор tableCell с didSelectRowAtIndex работающим. - person yonel; 30.01.2014

В iOS 5 UIScrollViews предоставляют свои panGestureRecognizer и pinchGestureRecognizer.

Итак, если вам не нужна поддержка более старых версий iOS, вы можете попробовать innerScrollView.panGestureRecognizer.minimumNumberOfTouches = 2.

РЕДАКТИРОВАТЬ: это не работает; scrollView по-прежнему воспринимает прикосновения. Я оставлю это здесь для дальнейшего использования.

Если вы не хотите, чтобы внутренний scrollView вообще обрабатывал панорамирование, вы могли бы (я не пробовал) просто удалить его panGestureRecognizer.

person fzwo    schedule 13.06.2012
comment
Я хочу, чтобы он управлял панорамированием, даже панорамированием одним пальцем. Я просто не хочу, чтобы он реагировал на события одного касания, проглатывал их. Что он и делает, даже после увеличения минимального количества касаний распознавателя жестов панорамирования. - person zoul; 13.06.2012
comment
Разве панорамирование одним пальцем не происходит в одно касание? Боюсь, я вас неправильно понял. Кстати, если вы найдете хорошее решение, мне было бы интересно его услышать. Я нахожу хаки ScrollView странно увлекательными. - person fzwo; 13.06.2012
comment
@zoul Кроме того, как вы, с точки зрения пользовательского интерфейса, хотите обрабатывать горизонтальное панорамирование и разбиение по страницам? Прокрутите до конца, затем страницу? - person fzwo; 13.06.2012
comment
Извините, я, наверное, слишком небрежно говорю с жаргоном. Я хочу, чтобы представление внутренней прокрутки игнорировало, когда пользователь касается экрана и поднимает палец, не перемещая его («щелчок», а не «перетаскивание»). У меня есть рабочее решение, сейчас я редактирую свой ответ. - person zoul; 13.06.2012
comment
@zoul Это называется Tap. Я думаю, что самым простым решением было бы создать UITapGestureRecognizer и прикрепить его к внутреннему ScrollView: [innerScrollView addTapGestureRecognizer:myTGR]. Этот TapGestureRecognizer затем вызовет в вашем контроллере метод, который обрабатывает касание. Это не игнорирование, но это, наверное, проще сделать. - person fzwo; 13.06.2012
comment
Я очень внимательно отношусь к игнорированию касания, потому что хочу сохранить слабую связь между контроллером «содержимого» и контроллером, реализующим разбиение на страницы. С распознавателем жестов должен быть дополнительный интерфейс для контроллера контента, чтобы сообщать о касаниях выше. (Это то, для чего уже существует цепочка респондентов.) Спасибо за обсуждение! - person zoul; 13.06.2012
comment
Интересно, что я создал подклассы UIScrollView, установил для себя собственный делегат, добавил self.panGestureRecognizer.minimumNumberOfTouches = 2 и другие подходящие методы масштабирования, вставил его в другой UIScrollView, и ваше решение сработало для меня. - person David Zorychta; 18.05.2013