首页 > 解决方案 > 将完整的编程自定义视图添加到 ViewController。自动布局问题

问题描述

创建自定义视图时,我真的不明白如何使用布局。

主要问题在这里:

rect.heightAnchor.constraint(equalTo: heightAnchor, multiplier: 0.5),
rect.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 1),

如果我使用乘数,它可以正常工作。但是如果我使用常量:

rect.widthAnchor.constraint(equalToConstant: self.frame.width)

它不起作用。

如何为我的自定义视图 autoLayout 约束使用任何 superView 帧大小?

class MainView: UIView {

    lazy var rect: UIView  = {
        let view = UIView()
        view.backgroundColor = .green
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)

        backgroundColor = .red
        layout()

    }

    func layout() {

        addSubview(rect)

        self.translatesAutoresizingMaskIntoConstraints = false

           NSLayoutConstraint.activate([
            rect.heightAnchor.constraint(equalTo: heightAnchor, multiplier: 0.5),
            rect.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 1),
               rect.centerYAnchor.constraint(equalTo: centerYAnchor),
               rect.centerXAnchor.constraint(equalTo: centerXAnchor)
           ])

       }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

class ViewController: UIViewController {


    let mainView = MainView(frame: .zero)

    override func loadView() {

        self.view = mainView
    }

标签: iosswiftautolayout

解决方案


如果我使用乘数,它可以正常工作。但是如果我使用常量: rect.widthAnchor.constraint(equalToConstant: self.frame.width)

这一定会发生,在您的 viewController 中,您实例化您的asmainViewlet mainView = MainView(frame: .zero)将触发frame 为零initMainView

你在里面调用布局init

override init(frame: CGRect) {
    super.init(frame: frame)

    backgroundColor = .red
    layout()

}

所以你基本上在MainView框架为时调用布局Zero此时如果你设置rect.widthAnchor.constraint(equalToConstant: self.frame.width)那么你本质上说的是rect.widthAnchor.constraint(equalToConstant: 0) 因此宽度设置为零

请仔细阅读声明,在这种情况下,您将矩形宽度锚设置为常数,即 0,因此即使在 UI 周期的未来阶段您MainView获得适当的宽度,矩形的宽度将始终为零,因为您将其设置为常数0 值。

但是我在 self.view= mainView 之前设置了 mainView.frame = view.frame

不幸的是,对于您的 rect,此语句来晚了一点 :) 在 mainView 的 init 中调用了布局,因此 rects 宽度锚已设置为常量 0。现在尽管您更新 mainView.frame,但您的 rect 永远不会费心更新其宽度,为什么会吗?它的约束已经解析为一个常数值,在这种情况下显然是“ 0 ”:)

rect.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 1),为什么这样有效?

在这里你说你的矩形的宽度锚等于你的宽度锚MainView,你没有将矩形的宽度锚设置为一个常数,而是将它设置为与 MainView 的宽度锚匹配,所以当 MainView 的框架最终设置为适当的值时,您的矩形也将更新其宽度以匹配 MainViews 宽度。

坦率地说multiplier: 1,在这种情况下没有任何意义,因为您试图匹配矩形的宽度以匹配 MainView 的宽度,如果您希望矩形的宽度与 MainView 的宽度成比例变化(例如 MainView 宽度的 50% 等) ) 只有这样乘数才有意义

自动布局约束只不过是数学方程式,正确理解/可视化它们是获得完美 UI 约束的关键

希望这可以帮助


推荐阅读