NSLayoutConstraint 将视图固定到父视图的底部边缘

Posted

技术标签:

【中文标题】NSLayoutConstraint 将视图固定到父视图的底部边缘【英文标题】:NSLayoutConstraint that would pin a view to the bottom edge of a superview 【发布时间】:2015-08-12 14:47:02 【问题描述】:

一个可重现的例子

class ViewController: UIViewController 

   var created = false

   override func viewDidLayoutSubviews() 
      super.viewDidLayoutSubviews()
      if !created 

         let scrollView = UIScrollView()
         scrollView.backgroundColor = UIColor.grayColor()
         view.addSubview(scrollView)

         let kidView = UIView()
         kidView.backgroundColor = UIColor.redColor()
         kidView.translatesAutoresizingMaskIntoConstraints = false

         scrollView.addSubview(kidView)

         scrollView.translatesAutoresizingMaskIntoConstraints = false
         kidView.translatesAutoresizingMaskIntoConstraints = false

         view.addConstraints(
            NSLayoutConstraint.constraintsWithVisualFormat("H:|[scrollView]|", options: .AlignAllLeft, metrics: nil, views: ["scrollView": scrollView])
         )
         view.addConstraints(
            NSLayoutConstraint.constraintsWithVisualFormat("V:|[scrollView]|", options: .AlignAllLeft, metrics: nil, views: ["scrollView": scrollView])
         )

         kidView.addConstraints([
            NSLayoutConstraint(item: kidView, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 100),
            NSLayoutConstraint(item: kidView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 100),
         ])

         scrollView.addConstraints([
            NSLayoutConstraint(item: kidView, attribute: .CenterX, relatedBy: .Equal, toItem: scrollView, attribute: .CenterX, multiplier: 1, constant: 0),
            NSLayoutConstraint(item: kidView, attribute: .Bottom, relatedBy: .Equal, toItem: scrollView, attribute: .Bottom, multiplier: 1, constant: 0),
//            NSLayoutConstraint(item: kidView, attribute: .CenterY, relatedBy: .Equal, toItem: scrollView, attribute: .CenterY, multiplier: 1, constant: 0),
         ])

         created = true
      
   


问题

我想将自定义视图与UIScrollView 的底部边缘对齐,但我似乎只能将其与顶部或垂直中心对齐。

scrollView.addConstraints([
    NSLayoutConstraint(
        item: circleContainerView, 
        attribute: .Top, 
        relatedBy: .Equal, 
        toItem: scrollView, 
        attribute: .Top, 
        multiplier: 1, 
        constant: 0),
])

scrollView.addConstraints([
    NSLayoutConstraint(
        item: circleContainerView, 
        attribute: .CenterY, 
        relatedBy: .Equal, 
        toItem: scrollView, 
        attribute: .CenterY, 
        multiplier: 1, 
        constant: 0),
])

但我想要的是有这样一张照片。我怎么去那里?

【问题讨论】:

【参考方案1】:

具有自动布局的 ScrollView 的工作方式不同,您可以通过设置 translatesAutoresizingMaskIntoConstraints = true 并显式设置 contentSize 来仅使用一个子视图。 或者你设置translatesAutoresizingMaskIntoConstraints = false,让它自己找出约束。

在您的情况下,您可以在滚动中添加一个不可见视图并将其固定到顶部并将其高度设置为scrollView.bounds.size.height,然后使用该不可见视图设置创建约束

像这样改变你的约束

scrollView.addConstraints([
    NSLayoutConstraint(
        item: circleContainerView, 
        attribute: .Bottom, 
        relatedBy: .Equal, 
        toItem: invisibleView, 
        attribute: .Bottom, 
        multiplier: 1, 
        constant: 0),
])

访问link了解更多详情,阅读纯自动布局方法

更新:您修改后的代码

class ViewController: UIViewController 

    var created = false

    override func viewDidLayoutSubviews() 
        super.viewDidLayoutSubviews()
        if !created 

            let scrollView = UIScrollView()
            scrollView.backgroundColor = UIColor.grayColor()
            view.addSubview(scrollView)

            let kidView = UIView()
            kidView.backgroundColor = UIColor.redColor()

            scrollView.addSubview(kidView)

            scrollView.translatesAutoresizingMaskIntoConstraints = false
            kidView.translatesAutoresizingMaskIntoConstraints = false

            scrollView.frame = view.bounds;
            scrollView.contentSize = view.bounds.size

            // Add an invisible view

            let inV = UIView()
            inV.backgroundColor = UIColor.clearColor()
            inV.translatesAutoresizingMaskIntoConstraints = false
            scrollView.addSubview(inV)


            view.addConstraints(
                NSLayoutConstraint.constraintsWithVisualFormat("H:|[scrollView]|", options: .AlignAllLeft, metrics: nil, views: ["scrollView": scrollView])
            )
            view.addConstraints(
                NSLayoutConstraint.constraintsWithVisualFormat("V:|[scrollView]|", options: .AlignAllLeft, metrics: nil, views: ["scrollView": scrollView])
            )

            var constraint = NSLayoutConstraint(item: inV, attribute: .Top, relatedBy: .Equal, toItem: scrollView, attribute: .Top, multiplier: 1, constant: 0)

            view.addConstraint(constraint)

            constraint = NSLayoutConstraint(item: inV, attribute: .Left, relatedBy: .Equal, toItem: scrollView, attribute: .Left, multiplier: 1, constant: 0)
            view.addConstraint(constraint)

            inV.addConstraints([
                NSLayoutConstraint(item: inV, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .Width, multiplier: 1, constant: 10),
                NSLayoutConstraint(item: inV, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .Height, multiplier: 1, constant: self.view.bounds.size.height),
                ])

            //

            kidView.addConstraints([
                NSLayoutConstraint(item: kidView, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .Width, multiplier: 1, constant: 100),
                NSLayoutConstraint(item: kidView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .Height, multiplier: 1, constant: 100),
                ])

            view.addConstraints([
                NSLayoutConstraint(item: kidView, attribute: .CenterX, relatedBy: .Equal, toItem: scrollView, attribute: .CenterX, multiplier: 1, constant: 0),
                NSLayoutConstraint(item: kidView, attribute: .Bottom, relatedBy: .Equal, toItem: inV, attribute: .Bottom, multiplier: 1, constant: 0),
                ])

            created = true
        
    


【讨论】:

感谢您的输入,但这会将子视图一直向上移动到父视图之上。我已经用完整的代码更新了我的问题以重现这种行为,它只有大约 40 行。 感谢您的更新!考虑到自动布局的工作原理,我现在明白为什么需要额外的视图了。

以上是关于NSLayoutConstraint 将视图固定到父视图的底部边缘的主要内容,如果未能解决你的问题,请参考以下文章

NSLayoutConstraint 等高不等分

NSLayoutConstraint 用于代码中未知数量的子视图

NSLayoutConstraint 将 centerX 约束到 superview 的另一侧

NSLayoutConstraint 用于 UITableView 上的视图

NSLayoutConstraint 后子视图中的 UIButton 未收到触摸

NSLayoutConstraint - 无法将子视图框架设置为父视图边界