ScrollView自動布局的實現(xiàn)方式

背景

開發(fā)中,可能會有一些頁面顯示的元素很多,可能會超出一個屏幕,但也不適合用 TableView 或者 CollectionView,此時我們一般會用 ScrollView,那么就會出現(xiàn)自動布局的問題。

實現(xiàn)方式

純代碼

特點

  • 編碼繁瑣:需要手寫控件
  • 安全:只要正確地設(shè)置約束或者 frame、contentSize,一般不會出現(xiàn)滾動問題

示例

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)
}

效果圖

Scrollview_純代碼實現(xiàn).gif

Storyboard + 內(nèi)部View

特點

  • 搭建界面簡單
  • 直觀
  • 需要占位視圖

頁面結(jié)構(gòu)如圖

Scrollview_SB_Innerview.png

可能出現(xiàn)的問題

  • ScrollView 中直接添加子元素,報錯:Has ambiguous scrollable content height
  • ScrollView 內(nèi)容超出屏幕仍不能滾動


    Scrollview_layout_error.png

實現(xiàn)滾動的代碼

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    
    let statusBarH: CGFloat = 20
    // 如果沒有導航欄,就返回狀態(tài)欄的高度
    let navH = gationController?.navigationBar.frame.maxY ?? statusBarH
    let deltaH = (screenH - navH) - bottomView.frame.maxY
    placeholderViewBottomConstraint.constant = deltaH
}

效果圖

Scrollview_SB+InnerView.gif

Storyboard + 外部View

特點

  • 搭建界面簡單
  • 直觀
  • 不需要占位視圖,不需要對 ScrollView 的布局做特殊處理
  • 需要處理外部視圖的 frame(如果沒有用戶交互,可以忽略)

頁面結(jié)構(gòu)如圖

Scrollview_SB+OutterView.png

可能出現(xiàn)的問題

  • ScrollView 中直接添加子元素,報錯:Has ambiguous scrollable content height
  • 當內(nèi)容超出屏幕高度時,必須得設(shè)置 ContainerView 的 frame,否則不能滾動或者超出屏幕部分不接受事件


    Scrollview_SB+OutterView_事件問題.png

實現(xiàn)滾動的代碼

override func viewDidLoad() {
    super.viewDidLoad()
    
    scrollView.addSubview(containerView)
}

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    var f = containerView.frame
    f.size.width = screenW
    // 這句代碼很重要,處理超出屏幕無法響應事件問題
    f.size.height = bottomView.frame.maxY
    containerView.frame = f
    scrollView.contentSize = CGSize(width: screenW, height: omView.frame.maxY)
}

效果圖

Scrollview_SB+OutterView.gif

總結(jié)

ScrollView 不能滾動的原因

  • contentSize 小于自身 frame 的尺寸
  • isScrollEnabled 屬性,不過它默認就是 true,默認無需設(shè)置
  • ScrollView 或者其父元素無法交互,此時我們需要檢查 isUserInteractionEnabled 屬性是否為 true

ScrollView 一直支持滾動

默認情況下,當 ScrollView 里的元素不足一個屏幕高度時,不能滾動,如需滾動(彈簧效果),需要設(shè)置 alwaysBounceVertical 屬性為 true(水平方向亦如此)

關(guān)于 ScrollView 布局的選擇

純代碼布局

如果是純代碼布局,只能用方式一。老老實實、一行一行代碼實現(xiàn)布局,雖然代碼繁雜,但是坑少。(現(xiàn)在仍有不少公司是這樣編程的)

界面布局

推薦方式三,這樣 ScrollView 和 其子元素分離,可以簡化很多約束問題,更直觀

以上代碼,適用于 Swift 3.0 語法。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容