OC学习10:UITableViw点击事件和页面上的手势冲突怎么解决?
举例说明
下面以一个例子讲解
图中 superView
有两个 subView
,分别是 testView
和 testBtn
。我们在 superView
和 testView
都重载 touchsBegan:withEvent、touchsEnded:withEvent、 touchsMoved:withEvent、touchsCancelled:withEvent方法
,并且在 superView
上添加单击手势 UITapGestureRecognizer
,action名为tapAction,给testBtn绑定action名为testBtnClicked。
主要代码如下:
- SuperView
1 | - (void)initUI{ |
- textView
1 | //testView |
- 情景O:注释 手势 ,分别点击
superView
和testView
:
1 | 2023-03-08 17:58:44.408166+0800 手势冲突[20427:1092257] =========> superView touchs Began |
- 情景A:单击 superView ,输出结果:
1 | 2023-03-08 17:32:44.983101+0800 手势冲突[20227:1064772] =========> superView touchs Began |
- 情景B:单击 testView,输出结果:
1 | 2023-03-08 17:43:16.370199+0800 手势冲突[20326:1077469] =========> testView touchs Began |
- 情景C:单击 testBtn,输出结果:
1 | 2023-03-08 17:43:40.690096+0800 手势冲突[20326:1077469] =========> click btn |
- 情景D:按住 testView,过3秒后或更久释放,输出结果:
1 | 2023-03-08 17:43:50.678603+0800 手势冲突[20326:1077469] =========> testView touchs Began |
情景 O、A、B
分析
开发文档可知:
Gesture Recognizers Get the First Opportunity to Recognize a Touch.
A window delays the delivery of touch objects to the view so that the gesture recognizer can analyze the touch first. During the delay, if the gesture recognizer recognizes a touch gesture, then the window never delivers the touch object to the view, and also cancels any touch objects it previously sent to the view that were part of that recognized sequence.
Google翻译:
手势识别器获得识别触摸的第一个机会。
一个窗口延迟将触摸对象传递到视图,使得手势识别器可以首先分析触摸。 在延迟期间,如果手势识别
器识别出触摸手势,则窗口不会将触摸对象传递到视图,并且还将先前发送到作为识别的序列的一部分的视图的任何触摸对象取消。
触摸事件首先传递到手势上,如果手势识别成功了,就会取消事件的继续传递
,否则,事件还是会被响应链处理。系统维持了与响应链关联的所有手势,事件首先传递给手势,然后才传递给响应链。这样我们就解释A和B的场景了
情景 C
分析:
iOS 开发文档里这样说:
In iOS 6.0 and later, default control actions prevent overlapping gesture recognizer behavior. For example, the default action for a button is a single tap. If you have a single tap gesture recognizer attached to a button’s parent view, and the user taps the button, then the button’s action method receives the touch event instead of the gesture recognizer. This applies only to gesture recognition that overlaps the default action for a control, which includes:
A single finger single tap on a UIButton, UISwitch, UISegmentedControl, UIStepper,and UIPageControl.A single finger swipe on the knob of a UISlider, in a direction parallel to the slider.A single finger pan gesture on the knob of a UISwitch, in a direction parallel to the switch.
Google 翻译为:
在iOS 6.0及更高版本中,默认控制操作可防止重叠的手势识别器行为。 例如,按钮的默认操作是单击。 如果您有一个单击手势识别器附加到按钮的父视图,并且用户点击按钮,则按钮的动作方法接收触摸事件而不是手势识别器。 这仅适用于与控件的默认操作重叠的手势识别,其中包括:
单个手指单击UIButton,UISwitch,UISegmentedControl,UIStepper和UIPageControl.
单个手指在UISlider的旋钮上滑动,在平行于滑块的方向上。在UISwitch的旋钮上的单个手指平移手势 与开关平行的方向。
- 因此,在情景C,点击testBtn的action,按钮获取了事件响应,不会把事件响应传递给父视图的supView
情景 C
分析:
- 长按testView已经不是单击事件了,tap手势就不会识别
实际开发中遇到的问题
父视图上先后添加了一个
UIGestureRecognizer
和一个UITableView
我们发现在点击
UITableView
的cell
的时候,并没有触发-(void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath;
方法。
分析
由于 cell 继承 cell -> UIView -> UIResponder,是可以接收和处理事件的,但是添加了 tap
后会导致 cell
响应链无法正常响应,导致 手势冲突
解决方法
在我们点击 cell
的时候,不让父视图的 手势
干扰子视图cell的点击事件或者说响应链正常传递,一般会重写 UIGestureRecognizerDelegate
中的 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
方法。
1 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{ |
- Post title:OC学习10:UITableViw点击事件和页面上的手势冲突怎么解决?
- Post author:张建
- Create time:2023-03-07 19:17:26
- Post link:https://redefine.ohevan.com/2023/03/07/OC/OC学习07:UITableViw点击事件和页面上的手势冲突怎么解决?/
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.