OC ScrollView里面含有拖动的TableView 如何响应拖动的手势

参考闲鱼的主页面,上半部分的View和下半部分的TableView:

首先拿到设计的UI控件:

@property (weak, nonatomic) IBOutlet UIScrollView *ContentScrollView;//外部的套用ScrollView
@property (weak, nonatomic) IBOutlet UITableView *DocterInfoTable;//这是ScrollView内部的TableView
@property (weak, nonatomic) IBOutlet UIStackView *DoctorTableStack;//这是想要ScrollView停留的点

 

我们需要给ContentScrollView一个新的Controller来响应多个手势,在.m文件中实现协议UIGestureRecognizerDelegate:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}

 然后在主界面里面实现<,UITableViewDelegate,UITableViewDataSource,UIScrollViewDelegate>协议:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
//NSLog(@"%@,%f",scrollView.class,CGRectGetMinY(_DoctorTableStack.frame) - _ContentScrollView.contentOffset.y);
    //NSLog(@"%@",NSStringFromCGRect(_DoctorTableStack.frame));

    if (CGRectGetMinY(_DoctorTableStack.frame) <= _ContentScrollView.contentOffset.y) {
        NSLog(@"禁止_ContentScrollView滑动");
        _ContentScrollView.contentOffset = CGPointMake(0, CGRectGetMinY(_DoctorTableStack.frame));
        
        if (_DocterInfoTable.contentOffset.y > 20) {
            doctorViewPull = true;
        }
        else
            doctorViewPull = false;
    }
    
    if (CGRectGetMinY(_DoctorTableStack.frame) >_ContentScrollView.contentOffset.y) {
        NSLog(@"不行_DocterInfoTable滑动");
        if (!doctorViewPull) {
            _DocterInfoTable.contentOffset = CGPointZero;
        }
        else
            _ContentScrollView.contentOffset = CGPointMake(0, CGRectGetMinY(_DoctorTableStack.frame));
        
        

    }
    
}

 首先contentoffset的值会瞬间大于50都有可能。所以依靠contentoffset可能会导致边界值的误差判断出问题!!!1._ContentScrollView.contentOffset.y代表的是咱们ScollView的偏移量,当他小于我们设定的位置的顶部的时候,我们不允许TableView进行偏移,也就是将其偏移量设置为CGPointZero。这样视觉上就是ScrollView在移动儿TableView并没有移动。

2.当_ContentScrollView.contentOffset.y一旦大于设定值的时候,禁止其再滑动,设置他的值永远停留在该设定值。但是当我们向上突然拉一下的时候ScrollView和TableView都会有contentoffset,于是会有可能进入第二个分支,也就是“不行_DocterInfoTablehu滑动”。于是我们就需要一个Flag来表示我的TableView进入了pan状态,你Scrollview就不要响应,你尽管会进入这个分支但是你的值依然是当前位置,我们的设定值。直到TableView的contentoffset变得足够小,这里我设置20作为参考,代表我开始响应pan状态。(也可以将设置为1更接近完美)

重点就是:当我的ScrollView滑到特定值的时候需要一个状态标志,ScrollView不再变化,TableView响应pan手势。我的TableView放弃响应pan手势的时机就是我的TableView的contentoffset的值至少大于0.1,也就是滑动到顶部。这就是两者的switch button

2019.7.4修复iphonex/xs中的使用问题
Code is here:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
        //NSLog(@"%@,%f,%f",scrollView.class,CGRectGetMinY(_DoctorTableStack.frame) , _ContentScrollView.contentOffset.y);
        //NSLog(@"%@,%f",scrollView.class,scrollView.contentOffset.y);
        //偏移量够不够达到设定值CGRectGetMinY(_DoctorTableStack.frame)
        if (CGRectGetMinY(_DoctorTableStack.frame) <= _ContentScrollView.contentOffset.y) {
            doctorViewPull = true;
            _ContentScrollView.contentOffset = CGPointMake(0, CGRectGetMinY(_DoctorTableStack.frame));
        }
        //尽管不停的调用,但是TableView和ScrollView分别不同的响应
        else{
                if (_DocterInfoTable.contentOffset.y < 0.0) {
                    doctorViewPull = false;
                }
                
            if (!doctorViewPull) {
                //NSLog(@"TTT1");
                _DocterInfoTable.contentOffset = CGPointZero;
            }
            else{
                //NSLog(@"TTT2");
                _ContentScrollView.contentOffset = CGPointMake(0, CGRectGetMinY(_DoctorTableStack.frame));
            }
        }
    
}
对于if语句,第一个满足条件的情况有且仅可能是 下到指定位置,并且依然继续下滑,所以直接将Flag拉满。然后如果向上拉一定进入else语句,然后就能通过判断是否TableView先拉到头使得退出TableView的pan状态
 

=================2019 11 12 修复 TableView 的点击手势被 ScrollView 遮盖的问题。
                if (_MainScrollView.scrollEnabled) {
                    _MainScrollView.contentOffset = CGPointMake(0, CGRectGetMinY(_StopCheck.frame));
                }
                _MainScrollView.scrollEnabled =NO;

            }

            if (!doctorViewPull) {
                if (!CGPointEqualToPoint(_HospitalTableView.contentOffset, CGPointZero)) {
                    _MainScrollView.scrollEnabled =YES;
                    _HospitalTableView.contentOffset = CGPointZero;
                }
            }

修改的段落如

 

2020 1.02

新版本:

    if (_MainScrollView.contentOffset.y > CGRectGetMinY(_StopCheck.frame)) {
        NSLog(@"as1");

        _MainScrollView.contentOffset = CGPointMake(0, CGRectGetMinY(_StopCheck.frame));
        mainScrolling = NO;
        tableScrolling = YES;
    }
    if (_MainScrollView.contentOffset.y < CGRectGetMinY(_StopCheck.frame)) {
        
        if (_tableView.contentOffset.y < 0) {
            _tableView.contentOffset = CGPointZero;
            tableScrolling = NO;
            mainScrolling = YES;
        }
        
        if (mainScrolling) {
            _tableView.contentOffset = CGPointZero;
            //tableScrolling = NO;
        }
        
        if (tableScrolling) {
            _MainScrollView.contentOffset = CGPointMake(0, CGRectGetMinY(_StopCheck.frame));
            //mainScrolling = NO;
        }
    }

 再次修改

    if (scrollView.tag != 0 && _MainScrollView.contentOffset.y >= CGRectGetMinY(_StopCheck.frame)) {
        //NSLog(@"as1");
        
        _MainScrollView.contentOffset = CGPointMake(0, CGRectGetMinY(_StopCheck.frame));
        mainScrolling = NO;
        tableScrolling = YES;
    }
    if (scrollView.tag != 0 && _MainScrollView.contentOffset.y <= CGRectGetMinY(_StopCheck.frame)) {
        //NSLog(@"as2 %f",_HospitalTableView.contentOffset.y);
        
        if (mainScrolling) {
            _HospitalTableView.contentOffset = CGPointZero;
            //tableScrolling = NO;
        }
        
        if (tableScrolling) {
            _MainScrollView.contentOffset = CGPointMake(0, CGRectGetMinY(_StopCheck.frame));
            //mainScrolling = NO;
        }
        if (_HospitalTableView.contentOffset.y <= 0) {
            _HospitalTableView.contentOffset = CGPointZero;
            tableScrolling = NO;
            mainScrolling = YES;
        }
    }

 

posted @ 2019-07-03 22:55  事不过三寻  阅读(542)  评论(0)    收藏  举报