将框架绑定到超级视图边界 UIView 扩展
Posted
技术标签:
【中文标题】将框架绑定到超级视图边界 UIView 扩展【英文标题】:Bind frame to superview bounds UIView extension 【发布时间】:2021-01-05 04:44:02 【问题描述】:我经常发现自己在编写这些代码行:
myView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
myView.topAnchor.constraint(equalTo: myView.superview.topAnchor),
myView.bottomAnchor.constraint(equalTo: myView.superview.bottomAnchor),
myView.leadingAnchor.constraint(equalTo: myView.superview.leadingAnchor),
myView.trailingAnchor.constraint(equalTo: myView.superview.trailingAnchor)
])
所以我正在考虑写一个扩展。像这样的:
extension UIView
func bindFrameToSuperviewBounds()
self.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
self.topAnchor.constraint(equalTo: self.superview.topAnchor),
self.bottomAnchor.constraint(equalTo: self.superview.bottomAnchor),
self.leadingAnchor.constraint(equalTo: self.superview.leadingAnchor),
self.trailingAnchor.constraint(equalTo: self.superview.trailingAnchor)
])
我的问题:
也许像这样的一些内置功能(或技术)已经存在,我只是不知道(不过我已经用谷歌搜索了很多)
(理论上)这段代码不等同于:
myView.translatesAutoresizingMaskIntoConstraints = true
myView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
理论上为什么?因为在实践中它绝对不是等价的。这种替代技术从未给我预期的结果。结果几乎是不可预测的。
回答cmets:
地点: 绿色(外部)矩形是一个 containerView (UIView)。 紫色(内部)矩形是我正在插入的 UIStackView。 如您所见,约束方法效果很好。
下一个是自动调整掩码方法的结果:
为什么会有三张图片? 因为每次新启动应用程序的结果都不同!
【问题讨论】:
要使非自动布局示例等效,您还必须添加myView.frame = myView.superview.bounds
。
第二个问题可能重复:***.com/questions/36434947/…
@Rob 我已经尝试了所有这些属性的所有可以想象的组合,但我从未得到相同的结果。我刚刚又试了一次你的建议。没有。
@Sweeper 是的,它相关且有趣。但他们没有讨论如何实现对等。
这种技术 (a) 将子视图的frame
设置为其父视图的bounds
; (b) 设置自动调整掩码,这正是我们在约束之前这样做的方式。我刚刚测试了它,它工作正常。您将需要创建一个MCVE 来显示问题。也许你有一些不相关的代码在事后改变了translatesAutoresizingMaskIntoConstraints
或autoresizingMask
。或者您还有其他一些相互冲突的约束。但是这种autoresizingMask
技术是一种久经考验的真正技术......
【参考方案1】:
这两种技术产生相同的行为:
extension UIView
func bindFrameToSuperviewBoundsWithConstraints()
translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
topAnchor.constraint(equalTo: superview!.topAnchor),
bottomAnchor.constraint(equalTo: superview!.bottomAnchor),
leadingAnchor.constraint(equalTo: superview!.leadingAnchor),
trailingAnchor.constraint(equalTo: superview!.trailingAnchor)
])
func bindFrameToSuperviewBoundsWithAutoResizingMask()
translatesAutoresizingMaskIntoConstraints = true
frame = superview!.bounds
autoresizingMask = [.flexibleWidth, .flexibleHeight]
考虑:
class ViewController: UIViewController
@IBOutlet weak var containerView: UIView!
weak var timer: Timer?
deinit
timer?.invalidate()
override func viewDidLoad()
super.viewDidLoad()
containerView.clipsToBounds = false
let blueView = UIView()
blueView.backgroundColor = .blue
containerView.addSubview(blueView)
blueView.bindFrameToSuperviewBoundsWithConstraints()
let redView = UIView()
redView.backgroundColor = .red
containerView.addSubview(redView)
redView.bindFrameToSuperviewBoundsWithAutoResizingMask()
// toggle between the red and blue views
blueView.isHidden = true
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) _ in
redView.isHidden = !redView.isHidden
blueView.isHidden = !blueView.isHidden
这会产生两个交替的子视图,每个子视图使用不同的技术,说明它们的帧是相同的:
如果您发现自动调整大小的蒙版解决方案产生的结果与约束方法不同,那么一定是发生了其他事情。
【讨论】:
嗯...这可能是一个最大不可重现的例子)))我已经更新了我的帖子,请看一下:)【参考方案2】:您好,您可以使用这样的扩展:
func constraint(to view: UIView, padding: CGFloat = 0)
self.translatesAutoresizingMaskIntoConstraints = false
self.topAnchor.constraint(equalTo: view.topAnchor, constant: padding).isActive = true
self.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -padding).isActive = true
self.leftAnchor.constraint(equalTo: view.leftAnchor, constant: padding).isActive = true
self.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -padding).isActive = true
并与另一个创建超级视图的捷径:
func constraintToSuperview(padding: CGFloat = 0)
guard let superview = self.superview else
return
self.constraint(to: superview, padding: padding)
【讨论】:
以上是关于将框架绑定到超级视图边界 UIView 扩展的主要内容,如果未能解决你的问题,请参考以下文章