将完整的编程自定义视图添加到 ViewController。自动布局问题
Posted
技术标签:
【中文标题】将完整的编程自定义视图添加到 ViewController。自动布局问题【英文标题】:Adding full programamticly custom view to ViewController. AutoLayout problems 【发布时间】:2020-05-16 06:45:56 【问题描述】:我真的不明白在创建自定义视图时如何使用布局。
主要问题在这里:
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
【问题讨论】:
当您创建MainView
时将其设置为.zero,如果您使用rect.widthAnchor.constraint(equalToConstant: self.frame.width)
,您的子视图怎么会有更好的框架?
我正在尝试在 self.view=mainView 之前设置 mainView.frame = view.frame,但它不会改变结果
【参考方案1】:
如果我使用乘数,它可以正常工作。但是如果我使用常量:
rect.widthAnchor.constraint(equalToConstant: self.frame.width)
这一定会发生,在您的 viewController 中,您将 mainView
实例化为
let mainView = MainView(frame: .zero)
这将触发 init
的 MainView
,帧为零
你在init
里面调用layout
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)
因此宽度设置为零
请仔细阅读声明,您将矩形宽度锚设置为 constant,在这种情况下为 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
在这种情况下毫无意义,因为如果您希望 rect 的宽度与 MainView 的宽度成比例变化(例如 50 MainView 宽度的 % 等)只有乘数才有意义
自动布局约束只不过是数学方程式,正确理解/可视化它们是获得具有约束的完美 UI 的关键
希望对你有帮助
【讨论】:
好的。现在它对我来说更容易获得。如果我理解正确,则无法使用 (equalTo: constant) ,其中常量是使用 superView 帧大小进行计算的计算属性。或者有什么方法可以通过 superView 的大小来初始化帧? 我找到的最佳解决方案是制作框架:CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)【参考方案2】:如何为我的自定义视图 autoLayout 约束使用任何 superView 帧大小?
只需删除多人游戏。
NSLayoutConstraint.activate([
rect.heightAnchor.constraint(equalTo: heightAnchor),
rect.widthAnchor.constraint(equalTo: widthAnchor),
rect.centerYAnchor.constraint(equalTo: centerYAnchor),
rect.centerXAnchor.constraint(equalTo: centerXAnchor)
])
【讨论】:
以上是关于将完整的编程自定义视图添加到 ViewController。自动布局问题的主要内容,如果未能解决你的问题,请参考以下文章
以编程方式将一堆自定义视图从 XIB 添加到 UIStackView
以编程方式将 UILabel 添加到自定义 tableViewCell