【问题标题】:How to use preservesSuperviewLayoutMargins in nested views如何在嵌套视图中使用preservesSuperviewLayoutMargins
【发布时间】:2017-02-20 15:29:50
【问题描述】:

我正在尝试通过嵌套视图层次结构使用preservesSuperviewLayoutMargins,但在 UIKit 上遇到了很多问题,并且想知道我做错了什么(或者这是否是一个真正的错误)。

我正在尝试布置一些视图(一些并排,一些相互上方),如下所示:

// Various combinations here will create different visual results (it will either work or won't)

let i1 = ImageView()
//let i1 = LabelView()
let i2 = ImageView()
//let i2 = LabelView()
let i3 = ImageView()
//let i3 = LabelView()

let view = LeftRight(left: i1, right: TopBottom(top: i2, bottom: i3))
//let view = LeftRight(left: TopBottom(top: i2, bottom: i3), right: i1)

通过一些布局,我可以让它工作,如下所示。您可以看到右侧的图像正确缩进了绿色视图,而绿色视图又正确缩进了白色视图。

但与其他人一起我很挣扎:

在应用程序中运行与此类似的代码会导致完全锁定和内存失控。

使用layoutMargins 完成缩进,如下所示:

let masterView = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
masterView.translatesAutoresizingMaskIntoConstraints = false
masterView.layoutMargins = UIEdgeInsets(top: 5.0, left: 5.0, bottom: 5.0, right: 5.0)

let subView = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
subView.translatesAutoresizingMaskIntoConstraints = false
subView.layoutMargins = UIEdgeInsets(top: 5.0, left: 5.0, bottom: 5.0, right: 5.0)

这是来自游乐场的图像布局示例。 The full playground project can be found here 并且可以轻松加载并在 XCode 中运行以了解我的意思。

class ImageView: UIView {

    init() {

        super.init(frame: CGRect(x: 0, y: 0, width: 1000, height: 1000))

        self.preservesSuperviewLayoutMargins = true
        self.layoutMargins = .zero

        let imageView = UIImageView(image: UIImage(named: "jesus"))
        imageView.contentMode = .center

        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.clipsToBounds = true
        self.clipsToBounds = true
        imageView.backgroundColor = UIColor.red

        self.addSubview(imageView)

        imageView.leftAnchor.constraint(equalTo: self.layoutMarginsGuide.leftAnchor).isActive = true
        imageView.rightAnchor.constraint(equalTo: self.layoutMarginsGuide.rightAnchor).isActive = true
        imageView.topAnchor.constraint(equalTo: self.layoutMarginsGuide.topAnchor).isActive = true
        imageView.bottomAnchor.constraint(equalTo: self.layoutMarginsGuide.bottomAnchor).isActive = true
    }
}

【问题讨论】:

  • 我无法理解“其他”案例中的问题所在。您只向我们显示黑屏,但没有代码。你能补充一些细节吗?
  • 代码都在操场上。太多了,所以我在这里只展示了基础知识。黑屏是因为布局系统似乎无法渲染!

标签: ios iphone swift uikit


【解决方案1】:

好的。发现你的问题。您的主视图和子视图都具有大小为 500x500 的框架和每个边缘 5 个点的 marginLayout。如果你用.zero 的框架实例化那些,那么一切都应该没问题。

更新

在您的 Playground 多花一点时间后,我还将它添加到 ImageView:

private var imageView: UIImageView!
override var intrinsicContentSize: CGSize {
    return imageView?.intrinsicContentSize ?? .zero
}

和标签视图:

private var textLabel: UILabel!
override var intrinsicContentSize: CGSize {
    return textLabel?.intrinsicContentSize ?? .zero
}

现在在 ImageViewLabelView 的 init 方法中使用这些实例属性而不是局部变量。这样做之后,似乎所有可能的组合都有效。如果您知道某个特定组合不知道,请告诉我,以便我进行测试。

【讨论】:

  • 您好,感谢您的浏览。您是否尝试过此解决方案,因为我最初使用的是 .zero 并且效果不佳?通过设置框架,我实际上能够让它工作得更频繁一些。它们都使用自动布局进行布局,因此初始帧无关紧要。
  • 我现在将更新我的答案以添加更多详细信息。我正要这样做。
  • 您好,我已经进行了您描述的更改,但仍然出现此组合的黑屏:let i1 = ImageView() let i2 = LabelView() let i3 = LabelView()
  • 这个组合好运吗?
【解决方案2】:

我相信你忘记了一些必需的东西。

  1. 在 ImageView 和 Label 上实现 intrinsicContentSize
  2. 在这 2 个 UIView 子类(TopBottom 和 LeftRight)中缺少使两个子视图具有相同宽度和高度的约束
  3. 右视图 (LeftRight) 仍未将其 translatesAutoresizingMaskIntoConstraints 属性设置为 false
  4. 添加最外层frame视图的constraint for bottom
  5. frame 视图上致电layoutIfNeeded()

    top.widthAnchor.constraint(equalTo: bottom.widthAnchor).isActive = true top.heightAnchor.constraint(equalTo: bottom.heightAnchor).isActive = true

【讨论】:

  • LeftRight 视图的右侧确实将其设置为 false:right.translatesAutoresizingMaskIntoConstraints = false
  • 我在发布这个问题之前尝试实现intrinsicContentSize,但无法让它工作......另外,为什么我需要在leftRight中设置宽度和高度相同/topBottom 视图?
  • 因为自动布局引擎无法仅使用当前约束来确定左/右视图的宽度和上/下视图的高度。
  • 在TopBottom的情况下,内容的内容拥抱导致视图与内容一样高。 - 高度只是顶部高度加上底部高度,不需要实现intrinsicContentSize(尽管它确实尝试过但没有成功)。即使您从 masterView 中删除 trailingAnchor,它仍然只是黑屏。你有它的工作吗?
  • 我认为您遇到了Layout Feedback Loop 问题。您可以在https://developer.apple.com/videos/play/wwdc2016/236/ 中找到有关此内容以及如何调查和调试它们的更多信息
猜你喜欢
  • 1970-01-01
  • 2011-05-22
  • 2011-06-17
  • 2018-01-31
  • 2017-02-01
  • 1970-01-01
  • 2019-03-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多