UIScrollView 嵌套二

在 UIScrollView 嵌套一 中存在 拖拽时会中断的情况 这是因为手势中断引起的。所以在做UIScrollView嵌套时,需要做多手势支持操作 

实现 快速滚动时 内外嵌套ScrollView 能够 无缝衔接 滚动操作

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {

    

    return YES;

}

#import <UIKit/UIKit.h>

//继承自 UIScrollView   innerScrollView必须使用此ScrollView
@interface GWScrollView : UIScrollView

@end



#import "GWScrollView.h"

@implementation GWScrollView

// 手势传递给父试图
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    
    return YES;
}

@end

如果是Swift 需要明确显示遵守UIGestureRecognizerDelegate协议 来实现 手势方法,否则无效

extension GWScrollView: UIGestureRecognizerDelegate {

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {

        return true;

    }

}

extension GWScrollView: UIGestureRecognizerDelegate {

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {

        return true;
    }
}

定义一个类 实例 用户保存 内外 scrollView 的滚动状态,这里不可使用 scrollView.scrollEnabled,因为scrollView.scrollEnabled = NO;时会阻止手势

#import <UIKit/UIKit.h>

@interface SyncScrollContext : NSObject

@property (nonatomic, assign) CGFloat maxOuterOffsetY;

@property (nonatomic, assign) CGFloat maxinnerOffsetY;

@property(nonatomic, assign) BOOL outerEnable;

@property(nonatomic, assign) BOOL innerEnable;

@end

#import <UIKit/UIKit.h>

@interface SyncScrollContext : NSObject

@property (nonatomic, assign) CGFloat maxOuterOffsetY;
@property (nonatomic, assign) CGFloat maxinnerOffsetY;
@property(nonatomic, assign) BOOL outerEnable;
@property(nonatomic, assign) BOOL innerEnable;

@end



#import "SyncScrollContext.h"

@implementation SyncScrollContext

@end

布局试图 outScrollerView 嵌套 innerScrollerView

#import "ScrollViewController.h"

#import "GWScrollView.h"

#import "SyncScrollContext.h"

@interface ScrollViewController ()<UIScrollViewDelegate>

@property(nonatomic, strong)UIScrollView *outScrollerView;

@property(nonatomic, strong)UIScrollView *innerScrollerView;

@property(nonatomic, strong)SyncScrollContext *syncScrollContext;

@end

@implementation ScrollViewController

- (void)viewDidLoad {

    [super viewDidLoad];

    

    self.syncScrollContext = [SyncScrollContext new];

    self.syncScrollContext.maxinnerOffsetY = 0.f;

    self.syncScrollContext.maxOuterOffsetY = 380.f;

    self.syncScrollContext.innerEnable = NO;

    self.syncScrollContext.outerEnable = YES;

    

    self.outScrollerView.frame = CGRectMake(10, 90, 300, 550);

    self.outScrollerView.contentSize = CGSizeMake(300, 1800);

    [self.view addSubview:self.outScrollerView];

    

    self.innerScrollerView.frame = CGRectMake(10, 400, 240, 300);

    self.innerScrollerView.contentSize = CGSizeMake(240, 800);

    [self.outScrollerView addSubview:self.innerScrollerView];

    

    UIView *v1 = [UIView new];

    v1.frame = CGRectMake(90, 0, 90, 90);

    v1.backgroundColor = UIColor.yellowColor;

    [self.innerScrollerView addSubview:v1];

    

    UIView *v2 = [UIView new];

    v2.frame = CGRectMake(90, 90, 90, 90);

    v2.backgroundColor = UIColor.redColor;

    [self.innerScrollerView addSubview:v2];

}

#pragma mark - UIScrollViewDelegate

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {

    if (scrollView == self.outScrollerView) {

            CGPoint contentOffset = scrollView.contentOffset;

        if (!self.syncScrollContext.outerEnable) {

            

            [self.outScrollerView setContentOffset:CGPointMake(0, self.syncScrollContext.maxOuterOffsetY)];

        }

        

        // 修改 内外scrollView 的滚动状态

        if (self.outScrollerView.contentOffset.y >= self.syncScrollContext.maxOuterOffsetY) {

            self.syncScrollContext.outerEnable = NO;

            self.syncScrollContext.innerEnable = YES;

            

            /*

             外层滚动到目标位置后 把滚动距离 传给内存 scrollView

             当外层 scrollerView 滚动到最大值后 内部scrollerView 接着滚动剩余部分

             */

            CGFloat offsetY = contentOffset.y - self.syncScrollContext.maxOuterOffsetY;

            CGPoint innerOffset = self.innerScrollerView.contentOffset;

            innerOffset.y += offsetY;

            [self.innerScrollerView setContentOffset:innerOffset];

            

        } else {

            self.syncScrollContext.outerEnable = YES;

            self.syncScrollContext.innerEnable = NO;

        }

        

    }

    else if (scrollView == self.innerScrollerView) {

        

        if (!self.syncScrollContext.innerEnable) {

            [self.innerScrollerView setContentOffset:CGPointMake(0, self.syncScrollContext.maxinnerOffsetY)];

        }

        // 修改 内外scrollView 的滚动状态

        if (self.innerScrollerView.contentOffset.y <= self.syncScrollContext.maxinnerOffsetY) {

            self.syncScrollContext.innerEnable = NO;

            self.syncScrollContext.outerEnable = YES;

        }else {

            self.syncScrollContext.innerEnable = YES;

            self.syncScrollContext.outerEnable = NO;

        }

    }

}

- (UIScrollView *)outScrollerView {

    if (!_outScrollerView) {

        _outScrollerView = [[GWScrollView alloc] init];

        _outScrollerView.delegate = self;

        _outScrollerView.backgroundColor = UIColor.blueColor;

    }

    return _outScrollerView;

}

- (UIScrollView *)innerScrollerView {

    if (!_innerScrollerView) {

        _innerScrollerView = [[GWScrollView alloc] init];

        _innerScrollerView.delegate = self;

        _innerScrollerView.backgroundColor = UIColor.grayColor;

    }

    return _innerScrollerView;

}

@end

#import "ScrollViewController.h"
#import "GWScrollView.h"
#import "SyncScrollContext.h"

@interface ScrollViewController ()<UIScrollViewDelegate>

@property(nonatomic, strong)UIScrollView *outScrollerView;
@property(nonatomic, strong)UIScrollView *innerScrollerView;
@property(nonatomic, strong)SyncScrollContext *syncScrollContext;

@end

@implementation ScrollViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.syncScrollContext = [SyncScrollContext new];
    self.syncScrollContext.maxinnerOffsetY = 0.f;
    self.syncScrollContext.maxOuterOffsetY = 380.f;
    self.syncScrollContext.innerEnable = NO;
    self.syncScrollContext.outerEnable = YES;
    
    self.outScrollerView.frame = CGRectMake(10, 90, 300, 550);
    self.outScrollerView.contentSize = CGSizeMake(300, 1800);
    [self.view addSubview:self.outScrollerView];
    
    self.innerScrollerView.frame = CGRectMake(10, 400, 240, 300);
    self.innerScrollerView.contentSize = CGSizeMake(240, 800);
    [self.outScrollerView addSubview:self.innerScrollerView];
    
    UIView *v1 = [UIView new];
    v1.frame = CGRectMake(90, 0, 90, 90);
    v1.backgroundColor = UIColor.yellowColor;
    [self.innerScrollerView addSubview:v1];
    
    UIView *v2 = [UIView new];
    v2.frame = CGRectMake(90, 90, 90, 90);
    v2.backgroundColor = UIColor.redColor;
    [self.innerScrollerView addSubview:v2];
}

#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {

    if (scrollView == self.outScrollerView) {
            CGPoint contentOffset = scrollView.contentOffset;
        if (!self.syncScrollContext.outerEnable) {
            
            [self.outScrollerView setContentOffset:CGPointMake(0, self.syncScrollContext.maxOuterOffsetY)];
        }
        
        // 修改 内外scrollView 的滚动状态
        if (self.outScrollerView.contentOffset.y >= self.syncScrollContext.maxOuterOffsetY) {
            self.syncScrollContext.outerEnable = NO;
            self.syncScrollContext.innerEnable = YES;
            
            /*
             外层滚动到目标位置后 把滚动距离 传给内存 scrollView
             当外层 scrollerView 滚动到最大值后 内部scrollerView 接着滚动剩余部分
             */
            CGFloat offsetY = contentOffset.y - self.syncScrollContext.maxOuterOffsetY;
            CGPoint innerOffset = self.innerScrollerView.contentOffset;
            innerOffset.y += offsetY;
            [self.innerScrollerView setContentOffset:innerOffset];
            
        } else {
            self.syncScrollContext.outerEnable = YES;
            self.syncScrollContext.innerEnable = NO;
        }
        
    }
    else if (scrollView == self.innerScrollerView) {
        
        if (!self.syncScrollContext.innerEnable) {
            [self.innerScrollerView setContentOffset:CGPointMake(0, self.syncScrollContext.maxinnerOffsetY)];
        }
        // 修改 内外scrollView 的滚动状态
        if (self.innerScrollerView.contentOffset.y <= self.syncScrollContext.maxinnerOffsetY) {
            self.syncScrollContext.innerEnable = NO;
            self.syncScrollContext.outerEnable = YES;
        }else {
            self.syncScrollContext.innerEnable = YES;
            self.syncScrollContext.outerEnable = NO;
        }
    }
}

- (UIScrollView *)outScrollerView {
    if (!_outScrollerView) {
        _outScrollerView = [[GWScrollView alloc] init];
        _outScrollerView.delegate = self;
        _outScrollerView.backgroundColor = UIColor.blueColor;
    }
    return _outScrollerView;
}

- (UIScrollView *)innerScrollerView {
    if (!_innerScrollerView) {
        _innerScrollerView = [[GWScrollView alloc] init];
        _innerScrollerView.delegate = self;
        _innerScrollerView.backgroundColor = UIColor.grayColor;
    }
    return _innerScrollerView;
}

@end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值