ios - 如何将 subview 放置在具有动态高度的 subview 下方?

标签 ios swift uiview autolayout

我有以下 UIView:

enter image description here

它是一个包含三个 subview 的 UIView。顶部有一个常规 UILabel (Hello World),一个自定义 UIViewController (CategoryList),其中包含一个带有按钮(alpha、beta、...)的 CollectionView 和另一个仅带有标签 (SALUT) 的自定义 UIViewController。

我以编程方式进行自动布局,并将 SALUT (var sCtrl) 放置在 CategoryList (var catList) 下方

sCtrl.view.topAnchor.constraint(equalTo: catList.view.bottomAnchor).isActive = true

这会产生上图,其中 SALUT 并未像我希望的那样位于类别列表下方。我有点明白为什么,因为当我设置约束时,按钮尚未在 CollectionView 中正确布局,因此未设置 catList 的底部 anchor 。

在 CategoryList:UIVIewController 中,我有以下内容以使 Collection View 获得正确的高度。

override public func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    heightConstraint = collectionView.heightAnchor.constraint(equalToConstant: collectionView.collectionViewLayout.collectionViewContentSize.height)
    self.view.addConstraint(heightConstraint)
}

这是可行的,但由于在 SALUT 上设置约束后调用 viewDidLayoutSubviews() ,因此 SALUT 位置是错误的。我怎样才能以简单的方式做到这一点? (我想我可以为我的主视图创建一个 Controller ,并在布局 subview 时检查那里,然后更新 subview 位置,但这对我来说似乎过于复杂)。

主视图的完整代码如下,以便您可以看到布局定位代码。如果需要,我还可以提供 subview 代码,但我认为不需要它,因为它们应该被视为黑匣子......

class MyView: UIView {

    let label = UILabel()
    var sCtrl : SubController
    var catList : CategoryList

    var topConstraint = NSLayoutConstraint()

    override init(frame: CGRect) {
        sCtrl = SubController()
        catList = CategoryList()
        super.init(frame: frame)
        setup()
    }

    private func setup() {
        self.backgroundColor = UIColor.green

        label.translatesAutoresizingMaskIntoConstraints = false
        label.backgroundColor = UIColor.yellow
        label.text = "Hello world"
        label.textAlignment = .center
        self.addSubview(label)

        catList.view.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(catList.view)

        sCtrl.view.translatesAutoresizingMaskIntoConstraints = false
        self.addSubview(sCtrl.view)

        let margins = self.layoutMarginsGuide

        label.leadingAnchor.constraint(equalTo: margins.leadingAnchor, constant: 0).isActive = true
        label.trailingAnchor.constraint(equalTo: margins.trailingAnchor, constant: 0).isActive = true
        label.topAnchor.constraint(equalTo: margins.topAnchor, constant: 0).isActive = true
        label.heightAnchor.constraint(equalToConstant: 100.0).isActive=true

        catList.view.leadingAnchor.constraint(equalTo: margins.leadingAnchor, constant: 0).isActive = true
        catList.view.topAnchor.constraint(equalTo: label.bottomAnchor, constant: 1.0).isActive = true
        catList.view.widthAnchor.constraint(equalTo: margins.widthAnchor, multiplier: 1.0).isActive = true
        catList.view.trailingAnchor.constraint(equalTo: margins.trailingAnchor, constant:0).isActive = true

        sCtrl.view.topAnchor.constraint(equalTo: catList.view.bottomAnchor).isActive = true
    }

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

}

let v = MyView(frame: CGRect(x: 0, y: 0, width: 400, height: 600))

最佳答案

好的,我发现了问题。我错过了将高度约束添加到 CategoryList 自己的 View 中。添加这个就可以了。

override public func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    heightConstraint = collectionView.heightAnchor.constraint(equalToConstant: collectionView.collectionViewLayout.collectionViewContentSize.height)
    self.view.addConstraint(heightConstraint)
    //THE MISSING LINE!!
    self.view.heightAnchor.constraint(equalTo: self.collectionView.heightAnchor, constant: 0).isActive = true
} 

关于ios - 如何将 subview 放置在具有动态高度的 subview 下方?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44281474/

相关文章:

ios - 我如何从 xib 创建自定义 uiview

ios - 无法在 Swift 中将 Anyobject 转换为 NSString

ios - 在 Swift 中使用 UITableView 以编程方式切换 View

ios - 使用 UIViewAnimationTransitionFlipFromRight 在按下时翻转 UIButton 并在 "the other side"上显示新按钮

ios - 使用 UIViewCells 创建计时器

ios - 如何在 Objective-C 中确定相同的 NSString?

ios - NSFetchedResultsController 缓存

ios - 将数据放入 UIView 容器中的嵌入式 TableView 中

ios - 使用 UIButton 转接 TableViewCell

swift - 下拉菜单标题与条形按钮重叠 - Swift