如果为子视图设置前导和尾随锚点,为什么 UIScrollView 不起作用?

Why UIScrollView don't work if you set leading and trailing anchors for subViews?

示例:

class ViewController: UIViewController {

  let labelOne: UIView = {
    let label = UIView()
    label.backgroundColor = .red
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
  }()

  let scrollView: UIScrollView = {
    let v = UIScrollView()
    v.translatesAutoresizingMaskIntoConstraints = false
    v.backgroundColor = .cyan
    v.contentSize = CGSize(width: 2000, height: 2000)
    return v
  }()


  override func viewDidLoad() {
    super.viewDidLoad()
    self.view.addSubview(scrollView)
    scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 8.0).isActive = true
    scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 8.0).isActive = true
    scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -8.0).isActive = true
    scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -8.0).isActive = true
    scrollView.addSubview(labelOne)
    
    labelOne.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 16.0).isActive = true
    labelOne.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 16.0).isActive = true
    labelOne.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -16).isActive = true
    labelOne.heightAnchor.constraint(equalToConstant: 100).isActive = true
  }
}

P.s 我知道如果我将内容视图放在 UIScrollView 中并在该内容中构建视图层次结构会更好,但我真的很想知道为什么会这样

看看这个...

我们设置labelOne(红色视图):

  • 宽度为 1968 磅(每边 2000 减去 16 磅)
  • 高度到 100 磅
  • 滚动视图 .contentLayoutGuide
  • 的顶部、前导和尾部距顶部、前导和尾部 16 磅
  • 距滚动视图底部 1884 点的底部 .contentLayoutGuide

所以:

class ViewController: UIViewController {
    
    let labelOne: UIView = {
        let label = UIView()
        label.backgroundColor = .red
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()
    
    let scrollView: UIScrollView = {
        let v = UIScrollView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.backgroundColor = .cyan
        // don't set this
        //v.contentSize = CGSize(width: 2000, height: 2000)
        return v
    }()
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.addSubview(scrollView)
        scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 8.0).isActive = true
        scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 8.0).isActive = true
        scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -8.0).isActive = true
        scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -8.0).isActive = true
        scrollView.addSubview(labelOne)

        // don't constrain directly to scrollView
        //labelOne.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 16.0).isActive = true
        //labelOne.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 16.0).isActive = true
        //labelOne.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -16).isActive = true
        //labelOne.heightAnchor.constraint(equalToConstant: 100).isActive = true
        
        // if we want horizontal scrolling of 2000-pts
        //  and labelOne to have 16-pts space on each side
        labelOne.widthAnchor.constraint(equalToConstant: 2000.0 - 32.0).isActive = true
        
        // labelOne height = 100
        labelOne.heightAnchor.constraint(equalToConstant: 100.0).isActive = true
        
        // use scrollView's Content Layout Guide
        let g = scrollView.contentLayoutGuide
        
        // labelOne 16-pts from top
        labelOne.topAnchor.constraint(equalTo: g.topAnchor, constant: 16.0).isActive = true
        
        // labelOne 16-pts from leading
        labelOne.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 16.0).isActive = true
        
        // labelOne 16-pts from trailing (so we can scroll 2000-pts
        labelOne.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -16.0).isActive = true
        
        // if we want vertical scrolling of 2000-pts
        //  and labelOne to be 100-pts tall with 16-pts on top
        //  constrain labelOne bottom (2000 - (100 + 16)) from content guide bottom
        labelOne.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -(2000.0 - (100.0 + 16.0))).isActive = true

    }
}