如何穿透TableView中的button滑动feeds流?

Posted yofer张耀琦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何穿透TableView中的button滑动feeds流?相关的知识,希望对你有一定的参考价值。

1. cell中的按钮如何透传滑动事件?

tableviewcell中画了一个button,但是从button开始滑动tableview会失效,造成一定几率tableview无法滑动。

1.1. UIView+UIImageView+UILabel 实现UIButton的效果

第1种方法:用一个UIView实现UIButton的效果。UIView中画button的背景,文字,还要实现touches的4个方法来自己处理button的高亮效果。

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

    [self addHighlightView]; // 点击开始的时候将背景色改为高亮色
    [super touchesBegan:touches withEvent:event];


- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

    [super touchesMoved:touches withEvent:event];


- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

    [self onclickContentView]; // 处理点击事件
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^
        [self unhighlightView];
    );
    [super touchesEnded:touches withEvent:event];


- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

    [self unhighlightView]; // 反高亮色
    [super touchesCancelled:touches withEvent:event];

1.2. 实现 touchesShouldCancelInContentView:,并返回YES

第2种方法:在tableview中,重载方法 touchesShouldCancelInContentView: ,像下面这样,就可以实现从button开始可以滑动tableview。

- (BOOL)touchesShouldCancelInContentView:(UIView *)view

    if ([view isKindOfClass:[UIButton class]]) 
        return YES;
    
    return [super touchesShouldCancelInContentView:view];

但发现这种方法在ios11以下的系统,会导致button的点击没有高亮态了。所以还需要在tableview的 init: 或者 initWithFrame: 中,加几行代码:

- (id)initWithFrame:(CGRect)frame 
    if (self = [super initWithFrame:frame style:UITableViewStylePlain]) 

        for (id view in self.subviews) 
            if ([view isKindOfClass:[UIScrollView class]]) 
                UIScrollView *scrollView = (UIScrollView *) view;
                scrollView.delaysContentTouches = NO;
            
        
    

    return self;

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 值。就可以达到视觉上位置固定不动了。

以上是关于如何穿透TableView中的button滑动feeds流?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 tableView 中创建自定义单元格(滑动单元格)

让 tableView 从 NSUserDefaults 中删除滑动删除项目 - 如何将这两个功能结合在一起?

实现cell显示一个删除button

如何优化tableView的使用?

UIView滑动手势与目标c中的tableview冲突

iOS解决嵌套在ScrollView中的TableView滑动手势冲突问题