在 App 開發(fā)中,基本上只要能滑動的 UI 都是 scrollView懊纳。
有時候感覺揉抵,蘋果這點做的非常不友好。為什么搞的這么麻煩嗤疯?
在其他的比如 HTML 中冤今,滑動無非就是超過了某個容器的可視范圍,于是就給了一個滑動條身弊。
很自然的一件事情辟汰。
到了蘋果這不光需要自己去注意這點。在使用純的 UISCrollView 的時候阱佛,我們還需要自己去手動計算可以滾動動的范圍帖汞。
吐槽歸吐槽,但 UIScrollView 的 contentSize 還是需要去計算的凑术。
情況一
我們知道 UIScrollView 里面每一個子元素的大小以及子元素的個數(shù)翩蘸。
比如:新特性界面
UIScrollView *sv = [[UIScrollView alloc] init];
sv.contentSize = CGSizeMake(圖片數(shù)量 * 圖片的寬, 圖片的高);
這種情況也非常簡單,數(shù)字和大小都是確定的淮逊。只需要帶入計算即可催首。
情況二
每一個子視圖的高度固定扶踊,但是子視圖的個數(shù)不確定。
在這里有就兩種做法了郎任。
第一種秧耗,申明一個 height 屬性,每次添加一個視圖的時候舶治,都根據(jù)前視圖的高度 & 邊距信息來記錄累加高度分井。
最后設置成 scrollView 的 contentSize.
UIScrollView *sv1 = [[UIScrollView alloc] init];
CGFloat height2 = 0;
UIView *c1 = [UIView new];
[sv1 addSubview:c1];
sv1.top = 20;
sv1.height = 300;
height2 += 300;
UIView *c2 = [UIView new];
c2.top = 40;
c2.height = 700;
height += 740;
// .........
sv1.contentSize = CGSizeMake(self.view.bounds.size.width, height2);
第二種情況,利用約束霉猛。
- 在 scrollView 中添加一個內(nèi)容容器 containerView尺锚。只設置約束 left ,top ,width。
- 然后再這個 containerView 中惜浅,添加各種子視圖瘫辩,并設置子視圖的位置和大小約束。
- 第一個子視圖必須設置 top 約束坛悉。
- 最后一個子視圖伐厌,必須設置一個 bottom 約束,用來計算 containerView 的 height 屬性吹散。
- 當約束計算完畢之后弧械,containerView 的 大小和位置就確定好了八酒。就可以間接的利用它來設置 scrollView 的 contentSize 了空民。
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:scrollView];
scrollView.showsHorizontalScrollIndicator = NO;
scrollView.alwaysBounceVertical = YES;
scrollView.backgroundColor = [UIColor whiteColor];
// 先不設置 contentSize.畢竟子視圖有多長還不知道
//scrollView.contentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, xxxx);
/**
不把 scrollView 的 contentSize 寫死,.
而是在其內(nèi)部放一個uiview.
在 uiview 內(nèi)部添加子視圖,用約束設置.
根據(jù)內(nèi)部約束的子視圖計算 uiview 的大小.
然后根據(jù) uiview 的大小設置 scrollView 的 contentSize.
*/
/**
現(xiàn)在的做法:
記錄每一個子視圖的高度記憶邊距數(shù)據(jù),然后累加起來.
*/
UIView *containerView = [[UIView alloc] init];
// 容器,只設置 x,y,w 高度 h 先不設置,用子視圖的約束去計算
[scrollView addSubview:containerView];
[containerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.offset(0);
make.width.equalTo(scrollView.mas_width);
}];
UIView *childView1 = [[UIView alloc] init];
[containerView addSubview:childView1];
childView1.backgroundColor = [UIColor blueColor];
[childView1 mas_makeConstraints:^(MASConstraintMaker *make) {
// 頭部約束
make.top.offset(20);
make.left.offset(0);
make.width.equalTo(containerView.mas_width);
make.height.offset(300);
}];
UIView *childView2 = [[UIView alloc] init];
[containerView addSubview:childView2];
childView2.backgroundColor = [UIColor greenColor];
[childView2 mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.offset(0);
make.top.equalTo(childView1.mas_bottom).offset(50);
make.height.offset(400);
make.width.equalTo(containerView.mas_width);
}];
UIView *childView3 = [[UIView alloc] init];
[containerView addSubview:childView3];
childView3.backgroundColor = [UIColor greenColor];
[childView3 mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.offset(0);
make.top.equalTo(childView2.mas_bottom).offset(100);
make.width.equalTo(containerView.mas_width);
make.height.offset(700);
// 底部約束,用于計算containerView 的 height
make.bottom.offset(-50);
}];
// 不用去調(diào)用約束立即計算的代碼,有個小技巧,使用 dispatch_after 即可拿到約束計算完畢之后的 containerView 的height 值.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"%.f",containerView.height);
scrollView.contentSize = CGSizeMake(self.view.width, containerView.height);
});
效果如下:
一個問題?
為什么要在 scrollView 中添加一個 containerView? 而不是直接往 scrollView 中直接添加子視圖羞迷?
因為 scrollView 本身的大小已經(jīng)確定了界轩。它不具備擴展和延伸性。
能夠延伸的是它內(nèi)部的 contentSize 尺寸下的子視圖衔瓮。
如果把 子視圖直接添加到 scrollView 浊猾,并添加約束,那么大小范圍热鞍,之后 scrollView 的 frame 那么大葫慎。
且子視圖可能會重疊在一起,甚至會出現(xiàn)約束沖突薇宠。
但是如果偷办,在scrollView 內(nèi)部添加一個 containerView 那么,它的大小就可以不確定了澄港。只用約束設置 left top width 椒涯。高度則是由其內(nèi)部的第一個子視圖的 top 約束以及最后一個子視圖的 bottom 約束計算得出即可。
最后在使用 dispatch_after 小技巧回梧,不需要提前計算約束废岂,就可以把 containerView 的 height 賦值給 scrollView 的 contentSize祖搓。