微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将约束与 Swift 中 UIView 上的可变高度和固定高度相结合

如何解决将约束与 Swift 中 UIView 上的可变高度和固定高度相结合

更新:

感谢大家的独特方法。欣赏您的见解。


背景:

我在下面的 Xcode Swift 5 中编写了一些代码,用于创建四个大小相等的矩形,这些矩形的大小取决于设备大小和方向。

然而,所需的结果是一个高度不同的矩形,其中顶部矩形的高度取决于设备大小和方向,底部矩形的高度恒定为 200px。


问题:

我需要对代码进行哪些更改才能实现顶部的可变高度和底部的固定高度?


代码

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let frametopLeft = UIView()
        frametopLeft.backgroundColor = .systemRed
        view.addSubview(frametopLeft)
        frametopLeft.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            frametopLeft.topAnchor.constraint(equalTo: view.topAnchor),frametopLeft.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.5),frametopLeft.leftAnchor.constraint(equalTo: view.leftAnchor),frametopLeft.widthAnchor.constraint(equalTo: view.widthAnchor,multiplier: 0.5)
        ])

        let frametopRight = UIView()
        frametopRight.backgroundColor = .systemBlue
        view.addSubview(frametopRight)
        frametopRight.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            frametopRight.topAnchor.constraint(equalTo: view.topAnchor),frametopRight.heightAnchor.constraint(equalTo: view.heightAnchor,frametopRight.rightAnchor.constraint(equalTo: view.rightAnchor),frametopRight.widthAnchor.constraint(equalTo: view.widthAnchor,multiplier: 0.5)
        ])

        let frameBottomLeft = UIView()
        frameBottomLeft.backgroundColor = .systemGreen
        view.addSubview(frameBottomLeft)
        frameBottomLeft.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            frameBottomLeft.bottomAnchor.constraint(equalTo: view.bottomAnchor),frameBottomLeft.heightAnchor.constraint(equalTo: view.heightAnchor,frameBottomLeft.leftAnchor.constraint(equalTo: view.leftAnchor),frameBottomLeft.widthAnchor.constraint(equalTo: view.widthAnchor,multiplier: 0.5)
        ])

        let frameBottomright = UIView()
        frameBottomright.backgroundColor = .systemYellow
        view.addSubview(frameBottomright)
        frameBottomright.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            frameBottomright.bottomAnchor.constraint(equalTo: view.bottomAnchor),frameBottomright.heightAnchor.constraint(equalTo: view.heightAnchor,frameBottomright.rightAnchor.constraint(equalTo: view.rightAnchor),frameBottomright.widthAnchor.constraint(equalTo: view.widthAnchor,multiplier: 0.5)
        ])

    }

}

图片

模拟器输出

Image of two iPads with four equal sized rectangles

所需的输出

Image of two iPads with two variable sized rectangles and two fixed sized rectangles

解决方法

使用 StackView 以获得更好的代码和理解。

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let topStack = UIStackView()
        topStack.axis = .horizontal
        topStack.distribution = .fillEqually
        
        let frameTopLeft = UIView()
        frameTopLeft.backgroundColor = .systemRed
        topStack.addArrangedSubview(frameTopLeft)
        
        
        let frameTopRight = UIView()
        frameTopRight.backgroundColor = .systemBlue
        topStack.addArrangedSubview(frameTopRight)
        
        
        let bottomStack = UIStackView()
        bottomStack.axis = .horizontal
        bottomStack.distribution = .fillEqually
        
        let frameBottomLeft = UIView()
        frameBottomLeft.backgroundColor = .systemGreen
        bottomStack.addArrangedSubview(frameBottomLeft)
        
        
        let frameBottomRight = UIView()
        frameBottomRight.backgroundColor = .systemYellow
        bottomStack.addArrangedSubview(frameBottomRight)
        
        frameBottomRight.translatesAutoresizingMaskIntoConstraints = false
        frameBottomRight.heightAnchor.constraint(equalToConstant: 200).isActive = true
        
        let mainStack = UIStackView()
        mainStack.axis = .vertical
        mainStack.addArrangedSubview(topStack)
        mainStack.addArrangedSubview(bottomStack)
        
        self.view.addSubview(mainStack)
        
        mainStack.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            mainStack.topAnchor.constraint(equalTo: view.topAnchor),mainStack.heightAnchor.constraint(equalTo: view.heightAnchor),mainStack.leftAnchor.constraint(equalTo: view.leftAnchor),mainStack.widthAnchor.constraint(equalTo: view.widthAnchor)
        ])
    }
    
}

或者您可以为每个底部视图提供相对约束。

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let frameTopLeft = UIView()
        frameTopLeft.backgroundColor = .systemRed
        view.addSubview(frameTopLeft)
        frameTopLeft.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            frameTopLeft.topAnchor.constraint(equalTo: view.topAnchor),//            frameTopLeft.heightAnchor.constraint(equalTo: view.heightAnchor,multiplier: 0.5),<< Here
            frameTopLeft.leftAnchor.constraint(equalTo: view.leftAnchor),frameTopLeft.widthAnchor.constraint(equalTo: view.widthAnchor,multiplier: 0.5)
        ])
        
        let frameTopRight = UIView()
        frameTopRight.backgroundColor = .systemBlue
        view.addSubview(frameTopRight)
        frameTopRight.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            frameTopRight.topAnchor.constraint(equalTo: view.topAnchor),//            frameTopRight.heightAnchor.constraint(equalTo: view.heightAnchor,<< Here
            frameTopRight.rightAnchor.constraint(equalTo: view.rightAnchor),frameTopRight.widthAnchor.constraint(equalTo: view.widthAnchor,multiplier: 0.5)
        ])
        
        let frameBottomLeft = UIView()
        frameBottomLeft.backgroundColor = .systemGreen
        view.addSubview(frameBottomLeft)
        frameBottomLeft.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            frameBottomLeft.topAnchor.constraint(equalTo: frameTopLeft.bottomAnchor),// << Here
            frameBottomLeft.bottomAnchor.constraint(equalTo: view.bottomAnchor),frameBottomLeft.heightAnchor.constraint(equalToConstant: 200),// << Here
            frameBottomLeft.leftAnchor.constraint(equalTo: view.leftAnchor),frameBottomLeft.widthAnchor.constraint(equalTo: view.widthAnchor,multiplier: 0.5)
        ])
        
        let frameBottomRight = UIView()
        frameBottomRight.backgroundColor = .systemYellow
        view.addSubview(frameBottomRight)
        frameBottomRight.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            frameBottomRight.topAnchor.constraint(equalTo: frameTopRight.bottomAnchor),// << Here
            frameBottomRight.bottomAnchor.constraint(equalTo: view.bottomAnchor),frameBottomRight.heightAnchor.constraint(equalToConstant: 200),// << Here
            frameBottomRight.rightAnchor.constraint(equalTo: view.rightAnchor),frameBottomRight.widthAnchor.constraint(equalTo: view.widthAnchor,multiplier: 0.5)
        ])
    }
}
,

您想给底部视图提供 200 的恒定高度约束,然后将顶部视图的底部约束到底部视图的顶部。

您可能会发现将相关代码组合在一起并随时添加注释很有帮助(让您相信代码应该做什么)。

所以,试试这样:

override func viewDidLoad() {
    super.viewDidLoad()

    // create 4 views
    let frameTopLeft = UIView()
    let frameTopRight = UIView()
    let frameBottomLeft = UIView()
    let frameBottomRight = UIView()

    // set background colors
    frameTopLeft.backgroundColor = .systemRed
    frameTopRight.backgroundColor = .systemBlue
    frameBottomLeft.backgroundColor = .systemGreen
    frameBottomRight.backgroundColor = .systemYellow

    // set Autoresizing and add to view
    [frameTopLeft,frameTopRight,frameBottomLeft,frameBottomRight].forEach { v in
        v.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(v)
    }

    NSLayoutConstraint.activate([
        
        // top-left view constrained Top / Left / 50% Width
        frameTopLeft.topAnchor.constraint(equalTo: view.topAnchor),frameTopLeft.leftAnchor.constraint(equalTo: view.leftAnchor),// top-right view constrained Top / Right / 50% Width
        frameTopRight.topAnchor.constraint(equalTo: view.topAnchor),frameTopRight.rightAnchor.constraint(equalTo: view.rightAnchor),// bottom-left view constrained Bottom / Left / 50% Width
        frameBottomLeft.bottomAnchor.constraint(equalTo: view.bottomAnchor),frameBottomLeft.leftAnchor.constraint(equalTo: view.leftAnchor),// bottom-right view constrained Bottom / Right / 50% Width
        frameBottomRight.bottomAnchor.constraint(equalTo: view.bottomAnchor),frameBottomRight.rightAnchor.constraint(equalTo: view.rightAnchor),// bottom views,constant Height of 200-pts
        frameBottomLeft.heightAnchor.constraint(equalToConstant: 200.0),frameBottomRight.heightAnchor.constraint(equalToConstant: 200.0),// constrain bottoms of top views to tops of bottom views
        frameTopLeft.bottomAnchor.constraint(equalTo: frameBottomLeft.topAnchor),frameTopRight.bottomAnchor.constraint(equalTo: frameBottomRight.topAnchor),])

}
,

我会这样做:

let frameTopLeft = UIView()
frameTopLeft.backgroundColor = .systemRed
view.addSubview(frameTopLeft)
frameTopLeft.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    frameTopLeft.topAnchor.constraint(equalTo: view.topAnchor),])

let frameTopRight = UIView()
frameTopRight.backgroundColor = .systemBlue
view.addSubview(frameTopRight)
frameTopRight.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    frameTopRight.topAnchor.constraint(equalTo: view.topAnchor),frameTopRight.leftAnchor.constraint(equalTo: frameTopLeft.rightAnchor),frameTopRight.widthAnchor.constraint(equalTo: frameTopLeft.widthAnchor)
])

let frameBottomLeft = UIView()
frameBottomLeft.backgroundColor = .systemGreen
view.addSubview(frameBottomLeft)
frameBottomLeft.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    frameBottomLeft.topAnchor.constraint(equalTo: frameTopLeft.bottomAnchor),frameBottomLeft.bottomAnchor.constraint(equalTo: view.bottomAnchor),])

let frameBottomRight = UIView()
frameBottomRight.backgroundColor = .systemYellow
view.addSubview(frameBottomRight)
frameBottomRight.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    frameBottomRight.topAnchor.constraint(equalTo: frameTopRight.bottomAnchor),frameBottomRight.bottomAnchor.constraint(equalTo: view.bottomAnchor),frameBottomRight.leftAnchor.constraint(equalTo: frameBottomLeft.rightAnchor),frameBottomRight.heightAnchor.constraint(equalTo: frameBottomLeft.heightAnchor),frameBottomRight.widthAnchor.constraint(equalTo: frameBottomLeft.widthAnchor),])

与其他人的主要区别是尽可能多地摆脱常量。

  1. 您的底部视图应该是 200?添加单个 200 约束,并使第二个视图高度等于第一个。
  2. 不是让宽度等于父级的 50%,你可以让左边的宽度等于右边的一个

它使您的代码更易于维护,减少了需要编辑的位置。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。