UIScrollView,是我们平时开发UI最常用的控件之一。并且我们常用的UITextView、UITableView、UICollectionView等等这些可滚动的控件,都是继承自UIScrollView来实现的。那么了解UIScrollView的滚动原理就十分必要了。
UIScrollView滚动的原理
frame和bounds
从UIScrollView的官方文档,我们可以知道,UIScrollView本质就是一个contentView的原点(origin)可调节的UIView,它会根据手指的移动,来相应的调节origin的值。
说到这里,我们先了解一些,UIView的frame和bounds属性,及其区别。
- frame:在父view的坐标系中的位置和尺寸。
- bounds: 在自己的坐标系中的位置和尺寸。默认bounds的origin为(0,0)。size和frame的size相同。
修改frame和bounds
而当我们更改frame和bounds的origin值时,会发生什么呢?
我们先创建三个view,分别是contentView、subView1、subView2。其中,subView1和subView2是contentView的两个子视图。其原始位置如下图:
![](https://img.haomeiwen.com/i993583/6e61d6c48cd61162.png)
我们来看一下修改subView1的bounds的origin,和subView2的frame的origin,如下图:
//更改subView1的bounds的origin
CGRect bounds = self.subView1.bounds;
bounds.origin = CGPointMake(20, 50);
self.subView1.bounds = bounds;
//更改subView2的frame的origin
CGRect frame = self.subView2.frame;
frame.origin = CGPointMake(20, 300);
self.subView2.frame = frame;
![](https://img.haomeiwen.com/i993583/a5c44613af714d24.png)
从图中,我们可以看到,subView2的frame的origin后,subView2的位置发生了改变,而修改subView1的bounds的origin的值,并不会影响subView1的位置。因为修改bounds的origin的值,改变的是subView1自身的坐标系,应该影响的是位于subView1自身的坐标系上的其子view。
那么,我们再修改contentView的bounds的origin的值,看看是否会影响contentView的子view的位置:
//更改contentView的bounds的origin
CGRect boundsContent = self.contentView.bounds;
boundsContent.origin = CGPointMake(0, -30);
self.contentView.bounds = boundsContent;
![](https://img.haomeiwen.com/i993583/0c6d24162db4c981.png)
可以发现,通过contentView的bounds的origin,改变了其上子view的位置,看起来好像是将子view向下滚动了。
由此可以看出,UIScrollView滚动就是通过改变其contentView的bounds的origin的值,使得contentView上的子视图有了滚动的效果。
UIScrollView如何判断是滑动还是子视图的点击的?
在触摸按下时,还会临时启动一个计时器,在计时器触发之前,看看触摸的手指是否有移动过。
如果计时器触发时,没有明显的位置改变,UIScrollView就会将事件传递给被触摸的子view。
如果计时器触发时,用户拖动手指足够远,UIScrollView就会取消给子view传递事件,并开始滚动。
网友评论