iOS development memo_UIScrollView

UIScrollView是你原本以為很簡單,但操作起來很麻煩的物件。

再加上如果沒熟讀文件的話,往往只能從錯誤之中學習,所花費時間成本相當高。

如果你用code建立就已經很麻煩了,沒想到用Storyboard建立又會更麻煩。

主要原因在於,原本你認知的UIScrollView其實與你想像的東西大為不同。

先從code來解說如下:

一般我們建立UIScrollView時,最重要要的property就是contentSize,因為由它來決定UIScrollView的滑動範圍。

當contentSize比SuperView的size大的時候,UIScrollView就會啟動滑動功能,因此contentSize的設定非常重要。

而當然不只是這樣,UIScrollView的contentSize則又要靠指定frame來建立,否則它不會有任何滑動變化。

基本的Code如下:

#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];

UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 900, 100, 30)];
label.text = @"Hello world!";
[self.scrollView addSubview:label];
self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width, label.frame.origin.y + 30);
}

上面的code透過IBOulet建立1個UIScrollView,另外建立一個UILabel物件,並指定該UILabel的frame,再把這個UILabel放到UIScrollView裡面,注意!裡面有非常重要的一點,就是把UIScrollView的contentSize的height,設為Label的y值在加30,代表UIScrollView的高會比Label的位置再高一點,留了一點空間較為美觀。

但是,如果想要在Sotryboard放上UIScrollView後,又想在裡面放元件時,情況就會完全不同了!

主要原因就是在於Constrain。

這邊就要提到用Storyboard建立UIScrollView的話,如果你constrain上下左右都設定為0,不會出現任何警告,

將scrollView上下左右都設為0

按確定後,沒有任何警告!OK!


接著,我們隨便放一個UIView到該UIScrollView裡面

But!就是這個But!如果在UIScrollView裡面放其他元件的話,UIScrollView就會傻了!

即使幫裡面的元件拉Constrain也沒用,還是錯誤

為什麼會這樣呢?

最主要的原因在原本你以為你拉的UIScrollView的大小就是它的實際大小,事實上不是!UIScrollView的大小是要根據contentSize的大小決定,而在storyboard裡面,放上UIScrollView後,它的contentSize的大小仍未決定,所以隨便放進一個元件,系統就傻了,Xcode不知道這個元件位在UIScrollView的哪個位置(因為沒有contentSize),即使你拉了constrain,但是autolayout所有元件的constrain,不是對於superView本身,而是對於superView的內容視圖(例如UIScrollView的contentSize),既然UIScrollVIew內容視圖並沒有被固定,而加入的UIView元件的frame卻依賴了scrollVIew的contentSize,而contentSize的值又要根據subView的frame來決定,兩邊都沒確定所以Xcode就傻了。

那為什麼普通把元件放在UIView裡面卻都沒事呢?

因為UIView元件的內容視圖就跟本身的frame大小一模一樣,把元件放在UIView裡面它自然就能對照該UIView的frame來確定自己的constrain,所以不會出現警告。

當然如果只是用純code來寫的話,如同最上面的code的例子,在viewDidLoad裡面設定UIScrollView的contentSize就可以解決了,但是如果使用Storyboard就要用另外一種做法。

假如要做到下面這個效果:

最簡單的做法就是在原本的ScrollView裡面再放一個UIView,並讓該UIVew除了上下左右對UIScrollView的Constrain設為0之外,也給它設定固定的高度(例如1000,比螢幕更長系統才會讓UIScrollView滑動)。如下圖

如此一來因為ScrollView裡面的UIView元件有高度,這樣ScrollView的contentSize就會自動根據UIView的高度去給值,如此一來高度的問題就滿足了。

但是這樣還沒結束,Xcode仍會給你警告,說你的寬度資訊不足,這時候就要再拉一個constrain,把UIView的寬跟ScrollView的寬設成equal width,如下圖

這樣警告就會消失,接著就可以自由地把元件放入UIView之中拉

所有放在UIView裡面的元件的constrain,以後都只要對著UIView就好了,不需要再去理UIScrollView,喔耶!

但是,上面的方法只能做固定高的UIScrollView,如果遇到要dynamic變化ScrollView的高度的話,得用其他方法!

目前經過自己本身的測試,如果要做動態的讓UIScrollView的高變長變短,則需要先確定UIScrollView裡面最下面的元件的位置(主要是y)。

並讓UIScrollView的contentSize的y值,跟著最下面的元件進行變化,就可以改變scrollView的高,在系統裡面,有沒有UIView的存在就不重要了,元件是直接addSubView在UIScrollVIew上,就如同最上方的code例子一樣。

以上是參考許多網路資源而來的,也用了一些網路資源的圖,其他用Storyboard來解決UIScrollView的問題可以參考以下的文章,概念都是一樣的,就是讓UIScrollView在storyboard的階段就知道自己的contentSize的大小!


One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.