天天看點

使用Xib(Storyboard)布局UIScrollView - 以及解決has ambiguous scrollable content width/height問題

概要

在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下的兩個屬性也會自動消失,接下來就可以用你熟悉的老辦法進行布局了。

使用Xib(Storyboard)布局UIScrollView - 以及解決has ambiguous scrollable content width/height問題

關閉Content Layout Guides後,如何使用之前的方式布局

在Xib中布局UIScrollView,其實主要就是兩件事:

1:為UIScrollView添加限制,确定UIScrollView的大小和位置。也就是确定顯示視窗;

2:在UIScrollView中添加一個内容視圖(想在UIScrollView中滾動的東西),為這個内容視圖添加限制,确定内容的大小和位置。也就是确定可滾動的内容;

使用Xib(Storyboard)布局UIScrollView - 以及解決has ambiguous scrollable content width/height問題

* 圖檔拍攝于2021.7 庫布齊沙漠

具體步驟:

1:拖動一個UIScrollView到螢幕,關閉Content Layout Guides選項,然後為此UIScrollView添加限制;

使用Xib(Storyboard)布局UIScrollView - 以及解決has ambiguous scrollable content width/height問題

給這個UIScrollView添加上下左右邊距後,這個UIScrollView就有了完整的限制,此時滾動視圖的顯示視窗位置也就固定了。

2:接下來開始添加并設定滾動内容。

這裡有一點需要注意,滾動視圖的内容大小(contentSize),是通過其内部的子視圖大小來計算的。一個滾動視圖内,可以包含多個子視圖,這些子視圖共同組成的矩形區域,才是滾動視圖的内容視圖大小。這個區域包含外層邊距以及中間空白的間距部分,如下圖:

使用Xib(Storyboard)布局UIScrollView - 以及解決has ambiguous scrollable content width/height問題

是以在設定内容視圖的限制時,必須滿足計算出完整内容大小的所有條件(邊距+長寬)。注意此處設定内容視圖邊距時(例如上圖中UIView1的頂邊距10),實際上是在設定UIScrollView的内容視圖大小,以及UIView1在整個内容區域中的偏移位置。

當内容區域長度(寬度)小于等于顯示區域的長(寬)時,視圖縱向(橫向)不可滾動;

了解了内容視圖的原理,實作就是一件很容易的事了,下面實作一個隻包含一個内容視圖,并且隻能垂直滾動的例子。

首先拖動一個UIView(也可以是其他視圖)到滾動視圖中,然後為這個内容視圖添加限制。

使用Xib(Storyboard)布局UIScrollView - 以及解決has ambiguous scrollable content width/height問題

 由于此時并未給内容視圖(UIView)添加寬度限制,是以滾動内容的寬度是無法計算的(隻知道邊距,不知道寬)。我們也可以直接給UIView設定一個固定的寬度,但是為了實作隻能垂直滾動的效果,設定UIView寬度等于UIScrollView寬度,顯然更加合理:

使用Xib(Storyboard)布局UIScrollView - 以及解決has ambiguous scrollable content width/height問題

至此UIScrollView和内容的所有限制都添加好了,在xib中是可以直接預覽滾動效果的(在滾動視圖上滑動滑鼠即可實作滾動), 添加後的限制情況如下圖:

使用Xib(Storyboard)布局UIScrollView - 以及解決has ambiguous scrollable content width/height問題

打開Content Layout Guides後,使用新方法進行布局

接下來研究一下Content Layout Guides。打開這個選先後,最明顯的差別就是UIScrollView下面出現了兩個新項目:

Content Layout guide - 用來設定滾動内容的大小;

Frame Layout Guide - 用來設定滾動視圖視窗大小;

也就是說我們可以實作不依賴滾動視圖的内容,來單獨控制滾動區域了。

依然是制作一個隻能上下滾動的demo。先拖動一個UIScrollView到視圖中,然後設定UIScrollView的四邊限制,設定四邊限制後,UIScrollView的大小和位置(視圖視窗)就确定了,也就是說新功能的第二項Frame Layout Guide不需要在進行任何設定了。

使用Xib(Storyboard)布局UIScrollView - 以及解決has ambiguous scrollable content width/height問題

由于 Content Layout guide還沒有設定,是以會提示如上錯誤。下面加入一個内容視圖,并設定内容視圖和Content Layout guide。

由于視圖内容區域不再由内容視圖計算,是以此處隻需要設定内容視圖(UIView)自己的寬度和高度即可,不需要在設定邊距。設定高度:

使用Xib(Storyboard)布局UIScrollView - 以及解決has ambiguous scrollable content width/height問題

 設定寬度仍然可以使用原來的方法,讓UIView寬度等于UIScrollView寬度,當然也可以借助Frame Layout Guide,因為Frame Layout Guide就是UIScrollView的視圖視窗,而且UIScrollView的frame已經确定了,是以我們隻要讓UIView寬度等于Frame Layout Guide的橫向寬度就行了,這樣顯得更合理。設定方法如下:

使用Xib(Storyboard)布局UIScrollView - 以及解決has ambiguous scrollable content width/height問題

 至此已經完成了内容UIView的寬高設定,也就是确定了内容的大小。接下來設定Content Layout guide,确定UIScrollView的滾動範圍。讓滾動範圍等于UIView大小,同樣是右鍵拖動UIView,到Content Layout guide上松開,然後按住Shift鍵選中四邊對齊,設定方法如下:

使用Xib(Storyboard)布局UIScrollView - 以及解決has ambiguous scrollable content width/height問題

以上設定使Content Layout guide(滾動範圍)的上下左右分别對齊到UIView的上下左右。設定完成後,對齊偏移量會使用視圖目前所在位置的值,需要手動修改一下,上下左右分别改為0,UIView與Frame Layout Guide的寬度比例改為1:

使用Xib(Storyboard)布局UIScrollView - 以及解決has ambiguous scrollable content width/height問題

 設定完的所有限制如下:

使用Xib(Storyboard)布局UIScrollView - 以及解決has ambiguous scrollable content width/height問題

現在可以在xib中預覽了。 Content Layout Guides的主要差別就是通過專門的屬性來設定内容視圖,可以使用UIScrollView外面的視圖來動态控制滾動視圖内容的大小,這樣之前某些必須通過代碼完成的功能,現在xib中也可以實作了。

DEMO :  https://github.com/zcsoft/XibScrollViewDemo

Create a UIScrollView using Auto Layout in Storyboard