iOS-UIScrollview滑动时标题栏自动隐藏和显示效果

来源:互联网 发布:关键词出价的算法 编辑:程序博客网 时间:2024/06/05 13:28

  本文主要介绍如何实现当UIScrollview滑动时,自动隐藏和显示标题栏的效果。其中布局采用Autolayout的方式,并且为了代码精简,使用了第三方库Masonry,其使用参考【iOS-Masonry学习笔记】。使用它的原因是可以很好的结合动画效果的实现!

一、布局

  首先我们来介绍一下整个布局。最外层的是一个UIScrollview(mainScrollview),其子视图包括一个模拟标题栏的UIView视图,以及一个UIScrollview视图(innerScrollview),并且其是按顺序上下排列的。其中的innerScrollview包含一个UIView容器子视图,并且该容器中包括若干个UIView子视图来模拟cell。其显示效果大致如下:

这里写图片描述

1.1 常量设置

    //屏幕宽度    #define UIScreenWidth [[UIScreen mainScreen] bounds].size.width    //屏幕高度    #define UIScreenHeight [[UIScreen mainScreen] bounds].size.height    //标题栏高度    NSInteger const titleHeight = 100;    //每个cell高度    NSInteger const cellHeight = 80;    //触发标题栏隐藏和显示事件的scrollview在Y方向上的滑动位移阈值    NSInteger const triggerToHideY = 200;

1.2 视图初始化

  整个布局的视图属性并不多,主要是一下这些。其中cells数组用于存储添加到container中的子UIView视图,以便于此后的视图约束设置。还有一个属性isHide是用来表示标题的状态的,如果标题隐藏则为YES,反之为NO,默认值为NO;

    @property (strong, nonatomic) UIScrollView *mainScrollview;    @property (strong, nonatomic) UIView *hideView;    @property (strong, nonatomic) UIScrollView *innerScrollview;    @property (strong, nonatomic) UIView *container;    @property (strong, nonatomic) NSMutableArray *cells;    @property (nonatomic) BOOL isHide;

接下来则是手动初始化各个视图对象,并设置它们的父子关系。

    - (void)viewDidLoad {        [super viewDidLoad];        //设置默认值        self.isHide = NO;        //初始化cells数组        self.cells = [NSMutableArray new];        //初始化mainScrollview视图        self.mainScrollview = [UIScrollView new];        [self.mainScrollview setBackgroundColor:[UIColor whiteColor]];        [self.view addSubview:self.mainScrollview];        //初始化hideView视图        self.hideView = [UIView new];        [self.hideView setBackgroundColor:[UIColor colorWithRed:0.000 green:0.502 blue:1.000 alpha:1.000]];        [self.mainScrollview addSubview:self.hideView];        //初始化container        self.container = [UIView new];        [self.container setBackgroundColor:[UIColor whiteColor]];        //初始化innerScrollView,默认开启弹簧效果        self.innerScrollview = [UIScrollView new];        self.innerScrollview.delegate = self;        //self.innerScrollview.bounces = NO;        [self.innerScrollview setBackgroundColor:[UIColor blackColor]];        [self.innerScrollview addSubview:self.container];        [self.mainScrollview addSubview:self.innerScrollview];        //生成若干个子视图,并添加到container中        for (int i = 0; i < 20; i++) {            UIView *view = [[UIView alloc] init];            [view setBackgroundColor:[UIColor colorWithRed:1-(i*10.0/255) green:1-(i*10.0/255) blue:1-(i*10.0/255) alpha:1.0f]];            [self.container addSubview:view];            [self.cells addObject:view];        }    }

1.3 视图约束

  视图的约束主要是采用Autolayout的布局思路,并使用第三方框架Masonry。哈哈大家可以看到使用框架之后省了好多代码量哈哈哈。

    -(void)updateViewConstraints    {        //设置mainScrollview约束        [self.mainScrollview mas_makeConstraints:^(MASConstraintMaker *make) {            //其边距与sel.view相等,即全屏显示            make.edges.equalTo(self.view);        }];        //设置hideView约束        [self.hideView mas_makeConstraints:^(MASConstraintMaker *make) {            //其上,左,右边距紧靠mainScrollview            make.top.left.right.equalTo(self.mainScrollview);            //X方向上居中            make.centerX.equalTo(self.mainScrollview);            //设置标题的高度            make.height.equalTo(@(titleHeight));        }];        //设置innerScrollview约束        [self.innerScrollview mas_makeConstraints:^(MASConstraintMaker *make) {            //其top紧靠标题的bottom,即它位于标题下方            make.top.equalTo(self.hideView.mas_bottom);            //左,右,下紧靠mainScrollview            make.left.and.right.equalTo(self.mainScrollview);            make.centerY.equalTo(self.mainScrollview).with.centerOffset(CGPointMake(0, titleHeight));        }];        //设置container约束        [self.container mas_makeConstraints:^(MASConstraintMaker *make) {            //containt主要约束为和innerScrollview的大小一致            make.edges.equalTo(self.innerScrollview);            make.width.equalTo(self.innerScrollview);        }];        //设置每个cell的约束        for (int i = 0; i < self.cells.count; i++) {            //获取需要约束的视图            UIView *subview = self.cells[i];            [subview mas_makeConstraints:^(MASConstraintMaker *make) {                make.right.left.centerX.equalTo(self.container);                make.height.equalTo(@(cellHeight));                //如果是第一个cell,则其top属性紧靠container容器                //否则每个cell的top属性紧靠上一个cell的bottom属性                if (i == 0) {                    make.top.equalTo(self.container);                }                else{                    UIView *topView = self.cells[i - 1];                    make.top.equalTo(topView.mas_bottom);                }            }];        }        //设置容器底部约束        [self.container mas_makeConstraints:^(MASConstraintMaker *make) {            //约束容器的bottom紧靠最后一个cell的bottom            //完成这个约束InnerScrollview就可以自动计算contentSize            //然后就可以滑动了!很神奇是不是!            UIView *lastView = self.cells[self.cells.count - 1];            make.bottom.equalTo(lastView.mas_bottom);        }];        //最后不要忘了调用超类的方法        [super updateViewConstraints];    }

二、自动隐藏和显示

  接下来就是如何实现自动隐藏和显示了。其实这个也很简单,了解UIScrollview的就会知道其有一个协议为UIScrollViewDelegate,其中包括了一些当scrollview滑动时会回调的函数,滑动动画开始、结束时的回调,用户手指拖拽和结束拖拽等诸多事件的回调。在这里我们主要用到的回调方法为scrollViewDidScroll:,就是当scrollview出现滑动事件时就会回调的方法。
所以首先要实现该协议。

    @interface ViewController () <UIScrollViewDelegate>

然后设置innerScrollview的delegate属性。

    self.innerScrollview.delegate = self;

  最后则是实现scrollViewDidScroll:方法。在方法里,先判断scrollview滑动的距离是否达到了触发自动隐藏和显示的阈值,然后判断当前标题栏的状态再是否需要进行动画隐藏和显示。其中动画实现的原理很简单,当需要隐藏标题栏时,则将标题视图移出视图(可以考虑将其也隐藏),并且重新设置InnerScrollview的显示区域。(更多UIScrollView相关参考【iOS实战-自定义的横向滚动控件CustomScrollView】)

    -(void)scrollViewDidScroll:(UIScrollView *)scrollView    {        if (scrollView.contentOffset.y > triggerToHideY) {            if (!self.isHide) {                self.isHide = YES;                [UIView animateWithDuration:0.3 animations:^{                    self.hideView.center = CGPointMake(self.hideView.center.x, -self.hideView.center.y);                    self.innerScrollview.frame = CGRectMake(0, 0, UIScreenWidth, UIScreenHeight);                }];            }        }        else if(scrollView.contentOffset.y < triggerToHideY){            if (self.isHide) {                self.isHide = NO;                [UIView animateWithDuration:0.3 animations:^{                    self.hideView.center = CGPointMake(self.hideView.center.x, -(self.hideView.center.y));                    self.innerScrollview.frame = CGRectMake(0, titleHeight, UIScreenWidth, UIScreenHeight);                }];            }        }    }

2.1 效果图

这就是大概的效果图,对于动画的一些设置可以调整一下(动画时间啊,动画时间函数什么的),可能会有更好的效果。

这里写图片描述

三、源代码

  工程的源代码已经上传到了Github上。由于本项目是使用了cocoapods进行第三方框架的引入,所以如果有问题的话可以考虑pod installpod update一下。如果还有别的问题可以联系我。

  项目为iOSDemon中的iOS_UI_study目录下的UIScrollviewAndHideView工程。
【传送门-iOSDemon-iOS_UI_study-UIScrollviewAndHideView】

0 0