scrollView.contentView才是其展现内容,对应的是contentSize,须要手动设置(相似frame)objective-c
在滑动时,实际改变的是scrollView.bounds.origin。浏览器
bounds是scrollView内部坐标系,bounds
的origin
,至关于原点的坐标值
。安全
拉列表,列表越长,contentOffset越大。 contentSize就是contentView的size。 contentSize、contentOffset和contentInset的图解辨别bash
Banner于TableViewapp
adjustContentInset
,表示contentView.frame.origin偏移了scrollview.frame.origin多少;是系统计算得来的,计算方式由contentInsetAdjustmentBehavior
决定。计算规则较复杂,iOS 11 安全区域适配总结不但愿上面Inset中自动修改,iOS11以前设置Controller的automaticallyAdjustsScrollViewInsets为NO,iOS11以后动画
if ([scrollview respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) {
scrollview.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
复制代码
做为controller.view
的第0个子视图
时,会自动修改contentInset和scrollIndicatorInsets属性,避免导航栏、TabBar的遮挡。ui
默认YES,即便用户滑到了头,仍是能够滑(可用于下拉刷新等),会显示背景色。spa
依赖于bounces=YES3d
默认NO,设置成YES,即便内容小于bounds,也能够拉。代理
只能中止在bounds的倍数上,配合UIPageControl能够实现轮播页的效果
放缩用
状态相关,拖曳、触碰、减速状态
refreshControl
iOS10UIRefreshControl
原理:经过-scrollViewDidScroll:代理方法,跟踪contentOffset的的变化。不知足悬停条件时,hidden。
原理:
经过-scrollViewDidScroll:代理方法跟踪contentOffset的的变化,根据contentOffset动态设置图片的缩放比例
// 以"动态修改图片缩放比例于1倍和2倍之间"为例
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat scale = 1 - (scrollView.contentOffset.y / 100);
scale = (scale >= 1) ? scale : 1;
scale = (scale <= 2) ? scale : 2;
imageView.transform = CGAffineTransformMakeScale(scale, scale);
}
复制代码
原理:
建立N+2个UIImageView
经过-scrollViewDidScroll:代理方法,跟踪contentOffset的的变化
在滑动到首尾两个图片处,设置contentOffset到真实图片处。
通常是用 childVC + UIPageViewController 实现
下面最后两个与scrollview无关
利用拖曳位置: 开始位置 + 中止&中止滑动位置,contentOffset判断
若是实时性要求高,能够在didScroll里面,按照时间间隔来判断(基本不会用到)
TableView、CollectionView 利用beginDragging + willDisplayCell:的contentOffset判断。
利用手势
利用touchesBegan:、touchesMoved:、touchesEnded:
滚动
//contentOffset发生变化时调用(包括拖曳、减速过程、直接代码设置)
- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
复制代码
手指相关,一次拖曳,只调用一次。
//1 将要开始拖拽页面(非实时)
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;
//2 将要中止拖曳时(以velocity为初速度,直到targetContentOffset中止。可经过修改targetContentOffset,调整位置)
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
//3 手指离开时,若是decelerate为NO时,表示`滑动动画结束`。
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView;
//4 判断中止动画,要配合2或3,才完备
- (void)scrollViewWillEndDecelerating:(UIScrollView *)scrollView;
复制代码
放缩
- (void)scrollViewDidZoom:(UIScrollView *)scrollView;
- (nullable UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView; // return a view that will be scaled. if delegate returns nil, nothing happens
- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view NS_AVAILABLE_IOS(3_2); // called before the scroll view begins zooming its content
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(nullable UIView *)view atScale:(CGFloat)scale;
复制代码
状态栏
// 当scrollView已经滑动到顶部时调用(仅当点击状态栏让scrollView滑动到顶部才调用)
- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView;
复制代码
// 当-setContentOffset:animated:/-scrollRectVisible:animated:方法动画结束时调用(仅当animated设置为YES时才调用)
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView;
复制代码
用户按下时,UIScrollView不知道用户的意图
在按下一瞬间,UIEvent传递完成后,不会马上响应,而是开始一个150ms的倒计时,并监听用户接下来的行为
倒计时结束前,手指发生移动,滚动contentView,优先识别为手势。
倒计时结束时,手指位置没改变,调用-touchesShouldBegin:withEvent:inContentView: 询问是否将事件的响应权交给子视图(NO则不传递,YES则传递,默认YES)
事件传递给子视图后,手指位置又发生了移动,调用-touchesShouldCancelInContentView:询问是否取消已传递给子视图的事件
这里原文中写的是,ScrollView会拦截UIEvent不传给子视图,根据经验,若是ScrollView嵌套ScrollView,仍是子ScrollView先响应,所以,传递应该仍是会传递的,可是谁来响应,依据是手势 & 响应链中说的,手势>UIControl>UIResponder。
UIScrollView的详细使用介绍和实现原理分析[2018.06.20更新]
只容许横向:
设置subview的frameY与scrollView的frameY相等,而后设置alwaysBounceVertical=No(默认就是No)