版权声明:本文为博主原创,如需转载请注明出处。
1. cell中的按钮如何透传滑动事件?
tableviewcell中画了一个button,但是从button开始滑动tableview会失效,造成一定几率tableview无法滑动。
1.1. UIView+UIImageView+UILabel 实现UIButton的效果
第1种方法:用一个UIView实现UIButton的效果。UIView中画button的背景,文字,还要实现touches的4个方法来自己处理button的高亮效果。
1 | - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event |
1.2. 实现 touchesShouldCancelInContentView:
,并返回YES
第2种方法:在tableview中,重载方法 touchesShouldCancelInContentView:
,像下面这样,就可以实现从button开始可以滑动tableview。
1 | - (BOOL)touchesShouldCancelInContentView:(UIView *)view |
但发现这种方法在iOS11以下的系统,会导致button的点击没有高亮态了。所以还需要在tableview的 init:
或者 initWithFrame:
中,加几行代码:
1 | - (id)initWithFrame:(CGRect)frame { |
1.2.1. 原因剖析:
UIScrollView中的 delaysContentTouches
属性。
苹果官方的文档解释:default is YES. if NO, we immediately call -touchesShouldBegin:withEvent:inContentView:. this has no effect on presses
delaysContentTouches
默认值为YES,即UIScrollView会在接受到手势是延迟150ms来判断该手势是否能触发UIScrollView的滑动事件;反之值为NO时,UIScrollView会立马将接受到的手势分发到子视图上。
只是将 delaysContentTouches
设置为NO还不够,因为这样的话你想要拖动UIScrollView而起点落在替他有手势识别的视图上是会拖不动的。 于是我们要重载 touchesShouldCancelInContentView
,此方法决定手势是否取消传递到View上,拖动UIScrollView是触发。返回NO时,拖动手势将留在UIScrollView上;返回YES时,则传到View上。
2. 屏幕上固定位置的button,如何透传滑动事件?
新问题:有个Button在屏幕上固定位置,不是tableview的subview。
此时如果直接将事件往下传会失败。因为原本的设计:button和tableview都是add在controller的self.view上,所以一旦button先拿到响应事件,它的super链上就不会有tableview了。
2.1. 解决方案:
画一个view,实现button的效果。然后将这个view,add到tableview上,此时的view会随着tableview的滑动而滑动。
为了使得view相对屏幕固定,可以用KVO监听tableview的 contentOffset
变化,随着 contentOffset
的变化来改变 view的 frame
。就是将view原本的 y
加上 offset
,就是这个view的新 y
值。就可以达到视觉上位置固定不动了。