概要
在xib中自动布局UIScrollView一直都是个挺麻烦的事。尤其从Xcode11开始,苹果对UIScrollView引入了“Content Layout Guides”,这导致默认情况下使用之前的方式布局会遇到“has ambiguous scrollable content width/height”错误。下面分别介绍一下如何关闭“Content Layout Guides”并继续使用老版本的布局方法,以及如何使用新方法进行布局。
解决has ambiguous scrollable content width/height问题
解决这个问题只需要关闭UIScrollView的“Content Layout Guides”功能即可,新版xcode默认会打开此功能,由于我们并没有对此功能进行设置,所以就导致了错误。关闭后,左侧视图结构中Scroll View下的两个属性也会自动消失,接下来就可以用你熟悉的老办法进行布局了。
关闭Content Layout Guides后,如何使用之前的方式布局
在Xib中布局UIScrollView,其实主要就是两件事:
1:为UIScrollView添加约束,确定UIScrollView的大小和位置。也就是确定显示窗口;
2:在UIScrollView中添加一个内容视图(想在UIScrollView中滚动的东西),为这个内容视图添加约束,确定内容的大小和位置。也就是确定可滚动的内容;
* 图片拍摄于2021.7 库布齐沙漠
具体步骤:
1:拖动一个UIScrollView到屏幕,关闭Content Layout Guides选项,然后为此UIScrollView添加约束;
给这个UIScrollView添加上下左右边距后,这个UIScrollView就有了完整的约束,此时滚动视图的显示窗口位置也就固定了。
2:接下来开始添加并设置滚动内容。
这里有一点需要注意,滚动视图的内容大小(contentSize),是通过其内部的子视图大小来计算的。一个滚动视图内,可以包含多个子视图,这些子视图共同组成的矩形区域,才是滚动视图的内容视图大小。这个区域包含外层边距以及中间空白的间距部分,如下图:
所以在设置内容视图的约束时,必须满足计算出完整内容大小的所有条件(边距+长宽)。注意此处设置内容视图边距时(例如上图中UIView1的顶边距10),实际上是在设置UIScrollView的内容视图大小,以及UIView1在整个内容区域中的偏移位置。
当内容区域长度(宽度)小于等于显示区域的长(宽)时,视图纵向(横向)不可滚动;
了解了内容视图的原理,实现就是一件很容易的事了,下面实现一个只包含一个内容视图,并且只能垂直滚动的例子。
首先拖动一个UIView(也可以是其他视图)到滚动视图中,然后为这个内容视图添加约束。
由于此时并未给内容视图(UIView)添加宽度约束,所以滚动内容的宽度是无法计算的(只知道边距,不知道宽)。我们也可以直接给UIView设置一个固定的宽度,但是为了实现只能垂直滚动的效果,设置UIView宽度等于UIScrollView宽度,显然更加合理:
至此UIScrollView和内容的所有约束都添加好了,在xib中是可以直接预览滚动效果的(在滚动视图上滑动鼠标即可实现滚动), 添加后的约束情况如下图:
打开Content Layout Guides后,使用新方法进行布局
接下来研究一下Content Layout Guides。打开这个选先后,最明显的区别就是UIScrollView下面出现了两个新项目:
Content Layout guide - 用来设置滚动内容的大小;
Frame Layout Guide - 用来设置滚动视图窗口大小;
也就是说我们可以实现不依赖滚动视图的内容,来单独控制滚动区域了。
依然是制作一个只能上下滚动的demo。先拖动一个UIScrollView到视图中,然后设置UIScrollView的四边约束,设置四边约束后,UIScrollView的大小和位置(视图窗口)就确定了,也就是说新功能的第二项Frame Layout Guide不需要在进行任何设置了。
由于 Content Layout guide还没有设置,所以会提示如上错误。下面加入一个内容视图,并设置内容视图和Content Layout guide。
由于视图内容区域不再由内容视图计算,所以此处只需要设置内容视图(UIView)自己的宽度和高度即可,不需要在设置边距。设置高度:
设置宽度仍然可以使用原来的方法,让UIView宽度等于UIScrollView宽度,当然也可以借助Frame Layout Guide,因为Frame Layout Guide就是UIScrollView的视图窗口,而且UIScrollView的frame已经确定了,所以我们只要让UIView宽度等于Frame Layout Guide的横向宽度就行了,这样显得更合理。设置方法如下:
至此已经完成了内容UIView的宽高设置,也就是确定了内容的大小。接下来设置Content Layout guide,确定UIScrollView的滚动范围。让滚动范围等于UIView大小,同样是右键拖动UIView,到Content Layout guide上松开,然后按住Shift键选中四边对齐,设置方法如下:
以上设置使Content Layout guide(滚动范围)的上下左右分别对齐到UIView的上下左右。设置完成后,对齐偏移量会使用视图当前所在位置的值,需要手动修改一下,上下左右分别改为0,UIView与Frame Layout Guide的宽度比例改为1:
设置完的所有约束如下:
现在可以在xib中预览了。 Content Layout Guides的主要区别就是通过专门的属性来设置内容视图,可以使用UIScrollView外面的视图来动态控制滚动视图内容的大小,这样之前某些必须通过代码完成的功能,现在xib中也可以实现了。
DEMO : https://github.com/zcsoft/XibScrollViewDemo
Create a UIScrollView using Auto Layout in Storyboard