ScrollableController

使用带有 UIScrollView 的 Autolayout 时,根据其内容或子视图的大小,它不会正确调整大小。

为了让 UIScrollView 在其内容变得太大而无法放入可见区域时自动滚动,我们需要添加一个 ContentView 和一些约束,允许 UIScrollView 确定其内容的大小及其父级的宽度和高度视图。

import Foundation
import UIKit

class ScrollableController : UIViewController {
    
    private var scrollView: UIScrollView!
    private var contentView: UIView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //Setup
        self.initControls()
        self.setTheme()
        self.layoutScrollView()
        self.layoutContentView()
        
        //Add child views
        self.addChildViews()
    }
    
    func initControls() {
        self.scrollView = UIScrollView()
        self.contentView = UIView()
    }
    
    func setTheme() {
        self.scrollView.backgroundColor = UIColor.blue()
        self.contentView.backgroundColor = UIColor.orange()
    }
    
    func layoutScrollView() {
        self.view.addSubview(self.scrollView)
        
        let views: NSDictionary = ["scrollView": self.scrollView]
        var constraints = Array<String>()
        
        //Constrain the scrollView to our controller's self.view.
        constraints.append("H:|-0-[scrollView]-0-|")
        constraints.append("V:|-0-[scrollView]-0-|")
        
        for constraint in constraints {
            self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: constraint, options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views as! [String : AnyObject]))
        }
        
        self.scrollView.translatesAutoresizingMaskIntoConstraints = false
    }
    
    func layoutContentView() {
        self.scrollView.addSubview(self.contentView)
        
        let views: NSDictionary = ["contentView": self.contentView, "view": self.view]
        var constraints = Array<String>()
        
        //Constrain the contentView to the scrollView.
        constraints.append("H:|-0-[contentView]-0-|")
        constraints.append("V:|-0-[contentView]-0-|")
        
        for constraint in constraints {
            self.scrollView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: constraint, options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views as! [String : AnyObject]))
        }
        
        //Disable Horizontal Scrolling by making the contentView EqualWidth with our controller's self.view (ScrollView's parentView).
        self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[contentView(==view)]", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views as! [String : AnyObject]))
        
        self.contentView.translatesAutoresizingMaskIntoConstraints = false
    }
    
    func addChildViews() {
        //Init
        let greenView = UIView()
        let whiteView = UIView()
        
        //Theme
        greenView.backgroundColor = UIColor.green()
        whiteView.backgroundColor = UIColor.orange()
        
        //Layout -- Child views are added to the 'ContentView'
        self.contentView.addSubview(greenView)
        self.contentView.addSubview(whiteView)
        
        let views: NSDictionary = ["greenView": greenView, "whiteView": whiteView];
        var constraints = Array<String>()
        
        //Constrain the greenView to the contentView with a height of 400 and 15 spacing all around.
        constraints.append("H:|-15-[greenView]-15-|")
        constraints.append("V:|-15-[greenView(400)]")
        
        //Constrain the whiteView below the greenView with 15 spacing all around and a height of 500.
        constraints.append("H:|-15-[whiteView]-15-|")
        constraints.append("V:[greenView]-15-[whiteView(500)]-15-|")
        
        for constraint in constraints {
            self.contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: constraint, options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views as! [String : AnyObject]))
        }
        
        greenView.translatesAutoresizingMaskIntoConstraints = false
        whiteView.translatesAutoresizingMaskIntoConstraints = false
    }
}

现在我们可以看到 greenView(400 高度)+ whiteView(500 高度)比我们的屏幕大。这将导致 ScrollView 的 contentSize 增长到适合两个视图,允许它垂直滚动。

我们在 contentViewself.view 上使用 EqualWidth 约束禁用了水平滚动

StackOverflow 文档