zoukankan      html  css  js  c++  java
  • iOS-关于一些手势冲突问题(scrollView 嵌套 tableView)

    简单说下关于开发中容易遇到的父试图添加手势与子试图点击事件冲突,UIScrollView 嵌套 UIScrollView 、 UIScrollView 嵌套 UITableView的情况手势冲突问题;

    点击冲突

    如果给现有的基于 UIView 的 xkTestView 上加一个点击手势 gestTap,然后在 xkTestView 中间区域添加一个 tableview,我们想响应 gestTap,同时也想响应 tableview 的 cell 点击代理事件,这时可以添加 gestTap 点击手势代理:

    <UIGestureRecognizerDelegate>

    然后在点击事件代理方法中实现

    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
        if ([NSStringFromClass([touch.view class]) isEqualToString:@"xkTestView"]) {
            return YES;
        }
        return  NO;
    }

     

    scrollView 嵌套 tableView 类冲突

    这里直接用 scrollView 嵌套 tableView 来处理下滑动时的手势冲突问题,其实苹果并不建议我们这样做,但是在实际项目中,有些需求会经常用嵌套来实现,在什么情况下滑动 tableView 不滑动 scrollView,什么情况下滑动 scrollView 不滑动 tableView,其实如果做其他的嵌套都是一样的,先看下最终效果图:

    1)首先新建一个基于 UIScrollView 的 XKBaseScrollView ,并实现 <UIGestureRecognizerDelegate> 代理,XKBaseScrollView 用做主父试图来添加子试图内容

     XKBaseScrollView.h

    #import <UIKit/UIKit.h>
    
    @interface XKBaseScrollView : UIScrollView <UIGestureRecognizerDelegate>
    
    @end

    XKBaseScrollView.m

    #import "XKBaseScrollView.h"
    
    @implementation XKBaseScrollView
    
    //是否支持多时候触发,这里返回YES
    -(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
        return YES;
    }
    
    @end

    2)然后新建一个基于 UITableView 的 XKTargetTableView ,并实现 <UIGestureRecognizerDelegate,UITableViewDelegate,UITableViewDataSource> 代理

    XKTargetTableView.h

    #import <UIKit/UIKit.h>
    
    
    @interface XKTargetTableView : UITableView
    ///可否滑动
    @property (nonatomic,assign) BOOL canSlide;
    ///滑动block通知
    @property (nonatomic,copy) void (^slideDragBlock)(void);
    @end

    XKTargetTableView.m

    #import "XKTargetTableView.h"
    @interface XKTargetTableView ()<UIGestureRecognizerDelegate,UITableViewDelegate,UITableViewDataSource>
    @property (nonatomic,assign) CGFloat currOffsetY;
    @end
    @implementation XKTargetTableView
    
    - (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style{
        self = [super initWithFrame:frame style:style];
        if (self) {
            self.backgroundColor = [UIColor whiteColor];
            self.delegate = self;
            self.dataSource = self;
            self.tableFooterView = [UIView new];
            [self registerClass:[UITableViewCell class] forCellReuseIdentifier:@"UITableViewCell"];
        }
        return self;
    }
    
    //是否支持多时候触发,这里返回YES
    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
        return YES;
    }
    
    #pragma mark ========== tableView 代理 ==========
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
        return 20;
    }
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
        return 50;
    }
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
        cell.textLabel.text = [NSString stringWithFormat:@"%ld",indexPath.row];
        return cell;
    }
    
    #pragma mark ========== scrollview 代理 ==========
    - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
        _currOffsetY = scrollView.contentOffset.y;
    }
    
    -(void)scrollViewDidScroll:(UIScrollView *)scrollView{
        if (!self.canSlide) {
            scrollView.contentOffset = CGPointMake(0, scrollView.contentOffset.y == 0 ? 0 : _currOffsetY);
        }
        _currOffsetY = scrollView.contentOffset.y;
        if (scrollView.contentOffset.y < 0 ) {
            self.canSlide = NO;
            scrollView.contentOffset = CGPointZero;
            //到顶通知父视图改变状态
            if (self.slideDragBlock) {
                self.slideDragBlock();
            }
        }
        scrollView.showsVerticalScrollIndicator = self.canSlide ? YES : NO;
    }
    @end

    3)最后在使用的 ViewController 中实现

    #import "ViewController.h"
    #import <SDAutoLayout.h>
    
    #import "XKBaseScrollView.h"
    #import "XKTargetTableView.h"
    
    @interface ViewController ()<UIScrollViewDelegate>
    ///容器
    @property (nonatomic,strong) XKBaseScrollView *scrollView;
    @property (nonatomic,strong) XKTargetTableView *tableView;
    ///是否可以滑动 scrollView
    @property (nonatomic,assign) BOOL canSlide;
    @property (nonatomic,assign) CGFloat lastPositionY;
    ///滑动临界范围值
    @property (nonatomic,assign) CGFloat dragCriticalY;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        _dragCriticalY = 200;
        [self.view addSubview:self.scrollView];
        self.scrollView.sd_layout.
        topSpaceToView(self.view, 0).
        leftSpaceToView(self.view, 0).
        rightSpaceToView(self.view, 0).
        bottomSpaceToView(self.view, 0);
        
        [self.scrollView setupAutoContentSizeWithBottomView:self.tableView bottomMargin:0];
        __weak __typeof__(self) weekSelf = self;
        self.tableView.slideDragBlock = ^{
            weekSelf.canSlide = YES;
            weekSelf.tableView.canSlide = NO;
        };
        
    }
    
    
    -(void)scrollViewDidScroll:(UIScrollView *)scrollView{
        CGFloat currentPostion = scrollView.contentOffset.y;
        /*
         当 底层滚动式图滚动到指定位置时,
         停止滚动,开始滚动子视图
         */
        if (currentPostion >= self.dragCriticalY) {
            scrollView.contentOffset = CGPointMake(0, self.dragCriticalY);
            if (self.canSlide) {
                self.canSlide = NO;
                self.tableView.canSlide = YES;
            }
            else{
                if (_lastPositionY - currentPostion > 0){
                    if (self.tableView.contentOffset.y > 0) {
                        self.tableView.canSlide = YES;
                        self.canSlide = NO;
                    }
                    else{
                        self.tableView.canSlide = NO;
                        self.canSlide = YES;
                    }
                }
            }
        }else{
            if (!self.canSlide && scrollView.contentOffset.y ==  self.dragCriticalY ) {
                scrollView.contentOffset = CGPointMake(0, self.dragCriticalY);
            }
            else{
                if (self.tableView.canSlide &&
                    self.tableView.contentOffset.y != 0) {
                    scrollView.contentOffset = CGPointMake(0, self.dragCriticalY);
                }
                else{
                    
                }
            }
        }
        
        _lastPositionY = currentPostion;
    }
    
    - (XKBaseScrollView *)scrollView{
        if (!_scrollView) {
            _scrollView = [[XKBaseScrollView alloc]init];
            _scrollView.showsVerticalScrollIndicator = NO;
       
            _scrollView.delegate = self;
            _scrollView.backgroundColor = [UIColor redColor];
            UIView *view = [[UIView alloc]init];
            view.backgroundColor = [UIColor blueColor];
            
            [_scrollView addSubview:view];
            view.sd_layout.
            topSpaceToView(_scrollView, 0).
            leftSpaceToView(_scrollView, 0).
            rightSpaceToView(_scrollView, 0).
            heightIs(300);
            
            [_scrollView addSubview:self.tableView];
            self.tableView.sd_layout.
            topSpaceToView(view, 0).
            leftSpaceToView(_scrollView, 0).
            rightSpaceToView(_scrollView, 0).
            heightIs(self.view.bounds.size.height - (300 - self.dragCriticalY));
        }
        return _scrollView;
    }
    - (XKTargetTableView *)tableView{
        if(!_tableView){
            _tableView = [[XKTargetTableView alloc]initWithFrame:CGRectZero style:UITableViewStylePlain];
        }
        return _tableView;
    }
    @end

    注:此 demo 需引用 SDAutoLayout

  • 相关阅读:
    layui动态修改select的选中项
    layui 鼠标悬停单元格显示全部
    使用LayUI操作数据表格
    layer.msg 弹出不同的效果的样式
    layer父页面刷新
    layui 获取radio单选框选中的值
    使用Dapper.Contrib
    微信公众号的文章爬取有三种方式
    centos的 各种安装包下载位置
    git pull一直弹出vim编辑器
  • 原文地址:https://www.cnblogs.com/wangkejia/p/11081577.html
Copyright © 2011-2022 走看看