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、付费专栏及课程。

余额充值