場景分析
在實際開發(fā)中遇到UIScrollView的場景大概分為兩類: 超過一個豎屏的信息展示 和 輪播圖,以少數(shù)派App做個例子

少數(shù)派.gif
技術(shù)難點
通常來說,UIScrollView的布局 有兩種方法:
- StoryBoard + AutoLayout的方式
- 代碼 + SnapKit布局的方式 進行
不管我們采取哪種布局技術(shù),如果我們直接在UIScrollView中添加子視圖,然后給子視圖相對于UIScrollView添加約束,會發(fā)現(xiàn)子視圖是無法顯示的,這是什么原因呢?
其實是因為: UIScrollView的leading/trailing/top/bottom是相對于自己的ContentSize來說的,而不是Frame; 而在給所有子視圖添加完視圖前ContentSize還不確定,我們這時候又給子視圖添加約束到ContentSize,相互依賴,不就成了蛋生雞,雞生蛋的問題了。
解決方案
我們可以給UIScrollView添加一個充滿自己的ContainerView,然后我們所有子視圖的布局相對于這個ContainerView就好了; 同時,只要確定了ContainerView的尺寸,也就確定了UIScrollView的ContentSize
干起來
我們通過SnapKit + 代碼的方式給一個垂直滾動的UIScollView加約束來做例子,其他情況原理都是類似的。
- Step1: 給UIScollView添加約束,沒什么可說的
view.addSubview(scrollView)
scrollView.snp.makeConstraints { (make) in
make.edges.equalToSuperview()
}
- step2 : 給UIScollView添加一個充滿他的ContainerView(重要)
注意:ContainerView給定了寬度,即UIScollView的ContentSize的寬度確定了,還需要確定高度
scrollView.addSubview(containerView)
containerView.snp.makeConstraints { (make) in
make.edges.equalToSuperview()
make.width.equalTo(ScreenWidth)
}
Step3: 在ContainerView中添加子視圖
//add 5 orange view
for i in 0..<5 {
let orangeView = UIView()
orangeView.backgroundColor = #colorLiteral(red: 0.9372549057, green: 0.3490196168, blue: 0.1921568662, alpha: 1)
containerView.addSubview(orangeView)
orangeView.snp.makeConstraints({ (make) in
make.left.right.equalTo(containerView)
make.height.equalTo(orangeViewGap)
if i == 0 {
make.top.equalTo(containerView.snp.top).offset(orangeViewGap)
} else if let previousView = containerView.subviews[i-1] as? UIView{
make.top.equalTo(previousView.snp.bottom).offset(orangeViewGap)
}
if i == 4 {
containerView.snp.makeConstraints({ (make) in
make.bottom.equalTo(orangeView.snp.bottom).offset(orangeViewGap)
})
}
})
}
上面代碼中,第一個View很簡單,關(guān)鍵是最后一個子視圖,一定要加好最后一個子視圖到ContainerView的間隔,即我們確定了ContainerView的高度,那么我們就確定了UIScrollView的ContentSize的高度,到此,完成整個布局過程; 核心代碼都在上面。
最終,完成效果如下:

ScrollView.gif