UIScrollView及其AutoLayout
之所以要把UIScrollView
单独拿出来说,是因为UIScrollView
在AutoLayout
时是一个比较特殊的视图。它特殊就特殊在它的Top
、Trailing
、Head
、Bottom
是相对于它的ContentSize
来设置的,而不是它的bounds
来设置的。
同时,要实现视图的滚动,UIScrollView
就得先知道要滚动的视图(UIScrollView
的子视图)的大小,这样才能够正确计算它要显示的各种数据(比如滚动条的大小、分页的多少)。
这样,你也许就不会好奇当你给UIScrollView
的子视图添加好Top
,Trailing
,Head
,Bottom
约束时,为什么Xcode还是会提示有错误了。
因为你添加的子视图要根据UIScrollView
的ContentSize
确定大小,而UIScrollView
的ContentSize
又要根据UIScrollView
的子视图确定其自身的大小。就这样,谁也不能确定自己的大小,所以Xcode就只能选择报错了。
使用AutoLayout的正确姿势
要解决上面的相互矛盾的问题。我们可以先在UIScrollView
上添加一个名叫ContentView
的子视图,让它根据UIScrollView
的宽和高(UIScrollView
的宽和高还是根据它自身的bounds
来确定的)来确定自身的大小,然后让UIScrollView
通过ContentView
来确定它的ContentSize
,再然后,把要添加的子视图添加到ContentView
上来,让子视图们根据ContentView
来确定自己的大小和位置。
这样,UIScrollView
的ContentSize
的大小也确定了,子视图的大小和位置也确定了,大家皆大欢喜,算是大功告成。
但是,还是会有那么一点点的小瑕疵在里面。
阻止ContentView
的向下偏移
之所以说有点小瑕疵在里面是因为当你按照上面的方法都把约束添加好了以后,比如说像下面ScrollView
这样:
和ContentView
这样:
在这里我让ContentView
与UIScrollView
等高等宽,ContentSize
的Top
,Bottom
,Head
,Trailing
分别等于ContentView
的对应属性,但是运行后却发现变成了下面这个样子:
这里我把ContentView
的背景色设置成了蓝色以便于观察。
你会发现ContentView
向下偏移了一段距离。
原来,从iOS7
开始,只要UIScrollView
是ViewController
的第一个子视图,并且顶部的导航栏不隐藏时,UIScrollView
中的子视图就会自动往下偏移64个像素,在这里UIScrollView
的子视图就是ContentView
了,所以ContentView
就会向下偏移了64像素。
要解决这个问题现在有下面两个方法:
- 不让
UIScrollView
成为第一个子视图。 - 调用
self.automaticallyAdjustsScrollViewInsets = NO
代码关掉自动偏移的功能。