正确的 UIGestureRecognizer 和委托设计
Proper UIGestureRecognizer and Delegate design
这是一个非常假设的问题,只是为了理解正确的设计,但假设我有两个自定义 UIView。
其中一个本质上是一个我称之为抽屉的容器。它的目的是隐藏和显示内容。它很像 iOS 上的通知中心,您可以在其中滑动以将其拉开,然后向上轻弹以将其关闭。它是一个通用容器,不能包含任何其他 UIView。它有一个 UIPanGestureRecognizer 来跟踪拉动它的手指 open/closed。它也可能有一个 UISwipeGestureRecognizer 来检测 "flick".
另一个视图是具有 UIPan/Rotation/Pinch GestureRecognizers 的自定义地图小部件。
我认为抽屉视图应该是 Pan/Swipe GestureRecognizers 的 UIGestureRecognizerDelegate,这样它就可以防止触摸传递,除非用户正在抓取 "the handle"。
我的第一直觉是让地图成为 pan/rotation/pinch 手势的 UIGestureRecognizerDelegate,这样它就可以让它们同时 运行。
我遇到的问题是,在抽屉完全打开之前,我真的不希望地图接收任何触摸或开始识别手势。我希望能够在抽屉本身中自动强制执行此行为,以便它适用于开箱即用的所有子视图。
我能想到的唯一方法是将所有手势处理程序连接到 ViewController 并让它做所有事情,但对我来说这会破坏封装,因为现在它必须知道地图手势需要同时 运行,抽屉只能触摸它的手柄,地图只能在打开时触摸。
有哪些方法可以让逻辑保留在我认为它所属的视图中?
我会做这样的事情来在平移时禁用抽屉的子视图。基本上遍历抽屉的子视图并取消对它们的交互。
[self.subviews enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop){
subview.userInteractionEnabled = NO;
}];
当您想在子视图上重新启用用户交互时,再次使用类似的东西。
这应该已经 Just Work™。手势识别器附加到视图;当识别出连续手势时,与该手势关联的所有后续触摸都与该视图关联。
所以在你的例子中,当抽屉盘被识别时,与该盘相关的任何触摸都不应该导致你的地图视图的 pan/pinch/rotation 手势行为(除非你明确指定他们应该使用适当的委托方法).
或者你的意思是你想阻止用户在打开抽屉的中途使用另一个手指(即另一个手势)开始滚动(半可见)地图?如果是这样,您应该将抽屉的 contentView
(或等效项)上的 userInteractionEnabled
设置为 UIGestureRecognizerStateBegan
/Changed
上的 NO
并再次设置 YES
UIGestureRecognizerStateEnded
/Cancelled
.
这是一个非常假设的问题,只是为了理解正确的设计,但假设我有两个自定义 UIView。
其中一个本质上是一个我称之为抽屉的容器。它的目的是隐藏和显示内容。它很像 iOS 上的通知中心,您可以在其中滑动以将其拉开,然后向上轻弹以将其关闭。它是一个通用容器,不能包含任何其他 UIView。它有一个 UIPanGestureRecognizer 来跟踪拉动它的手指 open/closed。它也可能有一个 UISwipeGestureRecognizer 来检测 "flick".
另一个视图是具有 UIPan/Rotation/Pinch GestureRecognizers 的自定义地图小部件。
我认为抽屉视图应该是 Pan/Swipe GestureRecognizers 的 UIGestureRecognizerDelegate,这样它就可以防止触摸传递,除非用户正在抓取 "the handle"。
我的第一直觉是让地图成为 pan/rotation/pinch 手势的 UIGestureRecognizerDelegate,这样它就可以让它们同时 运行。
我遇到的问题是,在抽屉完全打开之前,我真的不希望地图接收任何触摸或开始识别手势。我希望能够在抽屉本身中自动强制执行此行为,以便它适用于开箱即用的所有子视图。
我能想到的唯一方法是将所有手势处理程序连接到 ViewController 并让它做所有事情,但对我来说这会破坏封装,因为现在它必须知道地图手势需要同时 运行,抽屉只能触摸它的手柄,地图只能在打开时触摸。
有哪些方法可以让逻辑保留在我认为它所属的视图中?
我会做这样的事情来在平移时禁用抽屉的子视图。基本上遍历抽屉的子视图并取消对它们的交互。
[self.subviews enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop){
subview.userInteractionEnabled = NO;
}];
当您想在子视图上重新启用用户交互时,再次使用类似的东西。
这应该已经 Just Work™。手势识别器附加到视图;当识别出连续手势时,与该手势关联的所有后续触摸都与该视图关联。
所以在你的例子中,当抽屉盘被识别时,与该盘相关的任何触摸都不应该导致你的地图视图的 pan/pinch/rotation 手势行为(除非你明确指定他们应该使用适当的委托方法).
或者你的意思是你想阻止用户在打开抽屉的中途使用另一个手指(即另一个手势)开始滚动(半可见)地图?如果是这样,您应该将抽屉的 contentView
(或等效项)上的 userInteractionEnabled
设置为 UIGestureRecognizerStateBegan
/Changed
上的 NO
并再次设置 YES
UIGestureRecognizerStateEnded
/Cancelled
.