问题描述
更新:
感谢大家的独特方法。欣赏您的见解。
背景:
我在下面的 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)
])
}
}
图片:
模拟器输出。
所需的输出。
解决方法
使用 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),])
与其他人的主要区别是尽可能多地摆脱常量。
- 您的底部视图应该是 200?添加单个 200 约束,并使第二个视图高度等于第一个。
- 不是让宽度等于父级的 50%,你可以让左边的宽度等于右边的一个
它使您的代码更易于维护,减少了需要编辑的位置。