【问题标题】:Centering button with fixed width breaks NSLayoutConstraint具有固定宽度的居中按钮会中断 NSLayoutConstraint
【发布时间】:2019-02-06 06:31:36
【问题描述】:

我有一个有趣的问题。我的应用程序完全通过代码而不是故事板进行管理。我有一个以编程方式呈现的 UIViewController。它为它创建一个按钮和约束。

这就是控制器代码的样子。

import Foundation
import UIKit

class CreateViewController: UIViewController {

    lazy var button: UIButton = {
        let button =  UIButton()
        button.layer.bounds = CGRect(x: 0, y: 0, width: 50, height: 50)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.backgroundColor = .green
        return button
    }()

    func setupViews() {
        self.view.addSubview(button)
    }

    func setupConstraints() {
        self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[button]-100-|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: ["button": button]))
        self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[button(50)]-|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: ["button": button]))
    }

    override func viewDidLoad() {
        setupViews()
        setupConstraints()
    }
}

它会抛出这个错误。

(
    "<NSLayoutConstraint:0x60000288bb60 UIButton:0x7fa1ab422680.leading == UILayoutGuide:0x6000032da760'UIViewLayoutMarginsGuide'.leading NSSpace(0)   (active)>",
    "<NSLayoutConstraint:0x60000288bb10 UIButton:0x7fa1ab422680.width == 50   (active)>",
    "<NSLayoutConstraint:0x60000288d7c0 UILayoutGuide:0x6000032da760'UIViewLayoutMarginsGuide'.trailing == UIButton:0x7fa1ab422680.trailing NSSpace(0)   (active)>",
    "<NSLayoutConstraint:0x6000028fe990 'UIView-Encapsulated-Layout-Width' UIView:0x7fa1ab4224a0.width == 375   (active)>",
    "<NSLayoutConstraint:0x60000288fe30 'UIView-leftMargin-guide-constraint' H:|-(16)-[UILayoutGuide:0x6000032da760'UIViewLayoutMarginsGuide'](LTR)   (active, names: '|':UIView:0x7fa1ab4224a0 )>",
    "<NSLayoutConstraint:0x60000288d180 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x6000032da760'UIViewLayoutMarginsGuide']-(16)-|(LTR)   (active, names: '|':UIView:0x7fa1ab4224a0 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x60000288d7c0 UILayoutGuide:0x6000032da760'UIViewLayoutMarginsGuide'.trailing == UIButton:0x7fa1ab422680.trailing NSSpace(0)   (active)>

我的目标很简单。我希望按钮在底部上方 100 像素处,水平居中,并具有固定的宽度和高度。

这就是控制器被实例化的方式。它存在于

        let nav2 = UINavigationController()
        let create = CreateViewController()
        nav2.viewControllers = [create]
        nav2.navigationBar.isTranslucent = false
        ...
        let tabs = UITabBarController()
        tabs.viewControllers = [..., nav2, ...]

        tabs.delegate = self

任何帮助理解为什么会违反这些约束将不胜感激!如果问题的任何部分不清楚,请告诉我。

仅供参考,结果视图如下所示:

【问题讨论】:

    标签: ios swift autolayout nslayoutconstraint ios-autolayout


    【解决方案1】:

    使用视觉格式语言使元素居中是很困难的。

    您可以轻松使用.centerXAnchor

    class CreateViewController: UIViewController {
    
        lazy var button: UIButton = {
            let button =  UIButton()
            // next line is not needed
    //      button.layer.bounds = CGRect(x: 0, y: 0, width: 50, height: 50)
            button.translatesAutoresizingMaskIntoConstraints = false
            button.backgroundColor = .green
            return button
        }()
    
        func setupViews() {
            self.view.addSubview(button)
        }
    
        func setupConstraints() {
    
            NSLayoutConstraint.activate([
    
                // button width of 50
                button.widthAnchor.constraint(equalToConstant: 50.0),
    
                // button height of 50
                button.heightAnchor.constraint(equalToConstant: 50.0),
    
                // bottom of button 100-pts from bottom of view
                // note: contant is negative!
                button.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -100),
    
                // center the button horizontally
                button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
    
                ])
    
        }
    
        override func viewDidLoad() {
            setupViews()
            setupConstraints()
        }
    }
    

    【讨论】:

      【解决方案2】:

      您可以尝试以下方式添加更快捷、更简洁的约束

      func setupConstraints() {
          let topConstraint = NSLayoutConstraint(item: button,
                                                 attribute: .top,
                                                 relatedBy: .equal,
                                                 toItem: self.view,
                                                 attribute: .top,
                                                 multiplier: 1,
                                                 constant: 100)
      
          let bottomConstraint = NSLayoutConstraint(item: button,
                                                    attribute: .left,
                                                    relatedBy: .equal,
                                                    toItem: self.view,
                                                    attribute: .left,
                                                    multiplier: 1,
                                                    constant: 100)
          self.view.addConstraints([topConstraint,bottomConstraint])
      
      }
      

      虽然我想知道为什么要在按钮上添加约束,但什么时候可以在初始化时声明 x 和 y。如果您需要帮助,我也在按钮位于中心的位置添加了代码,希望对您有所帮助。

       lazy var button: UIButton = {
          let button =  UIButton()
          button.frame = CGRect(x: UIScreen.main.bounds.width/2-25, y: UIScreen.main.bounds.height/2-25, width: 50, height: 50)
          button.backgroundColor = .green
          return button
           }()  
      

      【讨论】:

        猜你喜欢
        • 2013-11-14
        • 2012-05-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-25
        • 2016-02-08
        • 2015-08-09
        相关资源
        最近更新 更多