背景
開發(fā)中,可能會(huì)有一些頁面顯示的元素很多娘荡,可能會(huì)超出一個(gè)屏幕干旁,但也不適合用 TableView 或者 CollectionView,此時(shí)我們一般會(huì)用 ScrollView炮沐,那么就會(huì)出現(xiàn)自動(dòng)布局的問題争群。
實(shí)現(xiàn)方式
純代碼
特點(diǎn)
- 編碼繁瑣:需要手寫控件
- 安全:只要正確地設(shè)置約束或者 frame、contentSize大年,一般不會(huì)出現(xiàn)滾動(dòng)問題
示例
lazy var scrollView: UIScrollView = {
let obj = UIScrollView(frame: CGRect(x: 0, y: 0, width: .screenW, height: self.screenH))
return obj
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(scrollView)
let subViewH: CGFloat = 400
let topView = UIView(frame: CGRect(x: 0, y: 0, width: enW, height: subViewH))
topView.backgroundColor = UIColor.red
scrollView.addSubview(topView)
let bottomView = UIView(frame: CGRect(x: 0, y: subViewH, h: screenW, height: subViewH))
bottomView.backgroundColor = UIColor.purple
scrollView.addSubview(bottomView)
scrollView.contentSize = CGSize(width: screenW, height: iewH * 2)
}
效果圖
Storyboard + 內(nèi)部View
特點(diǎn)
- 搭建界面簡(jiǎn)單
- 直觀
- 需要占位視圖
頁面結(jié)構(gòu)如圖
可能出現(xiàn)的問題
- ScrollView 中直接添加子元素换薄,報(bào)錯(cuò):Has ambiguous scrollable content height
-
ScrollView 內(nèi)容超出屏幕仍不能滾動(dòng)
實(shí)現(xiàn)滾動(dòng)的代碼
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let statusBarH: CGFloat = 20
// 如果沒有導(dǎo)航欄,就返回狀態(tài)欄的高度
let navH = gationController?.navigationBar.frame.maxY ?? statusBarH
let deltaH = (screenH - navH) - bottomView.frame.maxY
placeholderViewBottomConstraint.constant = deltaH
}
效果圖
Storyboard + 外部View
特點(diǎn)
- 搭建界面簡(jiǎn)單
- 直觀
- 不需要占位視圖翔试,不需要對(duì) ScrollView 的布局做特殊處理
- 需要處理外部視圖的 frame(如果沒有用戶交互轻要,可以忽略)
頁面結(jié)構(gòu)如圖
可能出現(xiàn)的問題
- ScrollView 中直接添加子元素,報(bào)錯(cuò):Has ambiguous scrollable content height
-
當(dāng)內(nèi)容超出屏幕高度時(shí)垦缅,必須得設(shè)置 ContainerView 的 frame伦腐,否則不能滾動(dòng)或者超出屏幕部分不接受事件
實(shí)現(xiàn)滾動(dòng)的代碼
override func viewDidLoad() {
super.viewDidLoad()
scrollView.addSubview(containerView)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
var f = containerView.frame
f.size.width = screenW
// 這句代碼很重要,處理超出屏幕無法響應(yīng)事件問題
f.size.height = bottomView.frame.maxY
containerView.frame = f
scrollView.contentSize = CGSize(width: screenW, height: omView.frame.maxY)
}
效果圖
總結(jié)
ScrollView 不能滾動(dòng)的原因
-
contentSize
小于自身 frame 的尺寸 -
isScrollEnabled
屬性失都,不過它默認(rèn)就是 true柏蘑,默認(rèn)無需設(shè)置 - ScrollView 或者其父元素?zé)o法交互幸冻,此時(shí)我們需要檢查
isUserInteractionEnabled
屬性是否為 true
ScrollView 一直支持滾動(dòng)
默認(rèn)情況下,當(dāng) ScrollView 里的元素不足一個(gè)屏幕高度時(shí)咳焚,不能滾動(dòng)洽损,如需滾動(dòng)(彈簧效果),需要設(shè)置 alwaysBounceVertical
屬性為 true(水平方向亦如此)
關(guān)于 ScrollView 布局的選擇
純代碼布局
如果是純代碼布局革半,只能用方式一碑定。老老實(shí)實(shí)、一行一行代碼實(shí)現(xiàn)布局又官,雖然代碼繁雜延刘,但是坑少。(現(xiàn)在仍有不少公司是這樣編程的)
界面布局
推薦方式三六敬,這樣 ScrollView 和 其子元素分離碘赖,可以簡(jiǎn)化很多約束問題,更直觀
以上代碼外构,適用于 Swift 3.0 語法普泡。