Правильный дизайн UIGestureRecognizer и Delegate

Это довольно гипотетический вопрос, просто чтобы понять правильный дизайн, но допустим, у меня есть два пользовательских UIView.

Один из них, по сути, представляет собой контейнер, который я назову ящиком. Его цель — скрыть и показать содержимое. Это очень похоже на центр уведомлений на iOS, где вы проводите пальцем, чтобы открыть его, и смахиваете его обратно, чтобы закрыть. Это универсальный контейнер, который может содержать любой другой UIView. У него есть UIPanGestureRecognizer для отслеживания пальца, который тянет его, открывая/закрывая. У него также может быть UISwipeGestureRecognizer для обнаружения «щелчка».

Другое представление представляет собой настраиваемый виджет карты с распознавателями жестов UIPan/Rotation/Pinch.

Я думаю, что вид ящика должен быть UIGestureRecognizerDelegate для Pan/Swipe GestureRecognizers, чтобы он мог предотвратить доставку касаний, если пользователь не захватит «ручку».

Мой первый инстинкт заключается в том, чтобы карта была UIGestureRecognizerDelegate жестов панорамирования/вращения/щипка, чтобы она могла позволить им выполняться одновременно.

Проблема, с которой я сталкиваюсь, заключается в том, что я действительно не хочу, чтобы карта получала какие-либо прикосновения или начинала распознавать жесты, пока ящик не будет полностью открыт. Я хотел бы иметь возможность автоматически применять это поведение в самом ящике, чтобы оно работало для всех подпредставлений прямо из коробки.

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

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


person cjserio    schedule 24.02.2015    source источник


Ответы (2)


Я бы сделал что-то подобное, чтобы отключить подвиды ящика во время панорамирования. По сути, прокручивайте подвиды ящика и отключайте взаимодействие с ними.

[self.subviews enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop){
    subview.userInteractionEnabled = NO;
}];

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

person lramirez135    schedule 24.02.2015
comment
Я не могу утверждать, что это решение не сработает, но оно выходит за рамки доступных инструментов жестов. Это потому, что у Superviews нет надлежащего способа управлять своим поведением жестов Subview (помимо того, что он является делегатом)? - person cjserio; 25.02.2015

Это уже должно работать Just Work™. Распознаватель жестов прикреплен к представлению; при распознавании непрерывного жеста все последующие касания, связанные с этим жестом, связываются с этим представлением.

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

Или вы имеете в виду, что хотите запретить пользователю на полпути открытия ящика использовать другой палец (то есть другой жест), чтобы начать прокрутку (полувидимой) карты? Если это так, вы должны просто установить userInteractionEnabled на contentView ящика (или аналогичный) на NO в UIGestureRecognizerStateBegan/Changed и снова YES в UIGestureRecognizerStateEnded/Cancelled.

person hatfinch    schedule 02.03.2015
comment
Фактический вариант использования заключается в том, что ящик находится в процессе перемещения (без прикосновения) из-за скорости, которую он получил от предыдущего перетаскивания/щелчка пальца... затем пользователь идет, чтобы остановить движение ящика, и касается карта (дочерняя), которая активирует перетаскивание карты... поэтому вместо того, чтобы остановить закрытие ящика, они перемещают карту, и ящик продолжает закрываться. Похоже, ваш третий абзац более применим, и вы предлагаете что-то очень похожее на то, что сделал lramirez135 в своем ответе. Кажется, это имеет смысл, поэтому я думаю, что мне нужно отдать ему должное. Но спасибо, что разъяснили. - person cjserio; 03.03.2015