【发布时间】:2026-02-14 14:15:02
【问题描述】:
我正在尝试复制 Apple 的计算器 UI 布局。
这是我目前所拥有的gif。
我遇到的问题主要与 UILables 有关。 如上图所示,我遇到了以下问题:
在设备旋转时,标签“L1”和“L2”弹出,而不是平滑过渡。
当转换回纵向时,棕色按钮上的标签会消失。
对于“L1”和“L2”标签,我尝试过尝试内容模式和约束,但是,我仍然会遇到笨拙的过渡。
至于消失的标签,我没有通过它的 is hidden 属性隐藏/取消隐藏堆栈视图以使布局出现和消失,而是尝试使用堆栈视图上的约束来处理转换,但是,结果仍然是一样。
我也在网上查看并尝试了一些建议,但是,大多数答案都已过时或根本不起作用。
代码非常简单,主要包括设置视图及其约束。
extension UIStackView {
convenience init(axis: UILayoutConstraintAxis, distribution: UIStackViewDistribution = .fill) {
self.init()
self.axis = axis
self.distribution = distribution
self.translatesAutoresizingMaskIntoConstraints = false
}
}
class Example: UIView {
let mainStackView = UIStackView(axis: .vertical, distribution: .fill)
let subStackView = UIStackView(axis: .horizontal, distribution: .fillProportionally)
let portraitStackView = UIStackView(axis: .vertical, distribution: .fillEqually)
let landscapeStackView = UIStackView(axis: .vertical, distribution: .fillEqually)
var containerView: UIView = {
$0.backgroundColor = .darkGray
$0.translatesAutoresizingMaskIntoConstraints = false
return $0
}(UIView(frame: .zero))
let mainView: UIView = {
$0.backgroundColor = .blue
$0.translatesAutoresizingMaskIntoConstraints = false
return $0
}(UIView(frame: .zero))
let labelView: UIView = {
$0.backgroundColor = .red
$0.translatesAutoresizingMaskIntoConstraints = false
return $0
}(UIView(frame: .zero))
var labelOne: UILabel!
var labelTwo: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .red
autoresizingMask = [.flexibleWidth, .flexibleHeight]
labelOne = createLabel(text: "L1")
labelOne.translatesAutoresizingMaskIntoConstraints = false
labelOne.backgroundColor = .darkGray
labelTwo = createLabel(text: "L2")
labelTwo.translatesAutoresizingMaskIntoConstraints = false
labelTwo.backgroundColor = .black
landscapeStackView.isHidden = true
mainView.addSubview(labelView)
labelView.addSubview(labelOne)
labelView.addSubview(labelTwo)
addSubview(mainStackView)
mainStackView.addArrangedSubview(mainView)
setButtonStackView()
setStackViewConstriants()
setDisplayViewConstriants()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setStackViewConstriants() {
mainStackView.translatesAutoresizingMaskIntoConstraints = false
mainStackView.topAnchor.constraint(equalTo: topAnchor).isActive = true
mainStackView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
mainStackView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
mainStackView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
}
func setDisplayViewConstriants() {
mainView.heightAnchor.constraint(equalTo: heightAnchor, multiplier: 288/667).isActive = true
labelView.heightAnchor.constraint(equalTo: mainView.heightAnchor, multiplier: 128/288).isActive = true
labelView.centerYAnchor.constraint(equalTo: mainView.centerYAnchor).isActive = true
labelView.leadingAnchor.constraint(equalTo: mainView.leadingAnchor, constant: 24).isActive = true
labelView.trailingAnchor.constraint(equalTo: mainView.trailingAnchor, constant: -24).isActive = true
labelOne.heightAnchor.constraint(equalTo: labelTwo.heightAnchor, multiplier: 88/32).isActive = true
labelOne.trailingAnchor.constraint(equalTo: labelView.trailingAnchor).isActive = true
labelOne.leadingAnchor.constraint(equalTo: labelView.leadingAnchor).isActive = true
labelOne.topAnchor.constraint(equalTo: labelView.topAnchor).isActive = true
labelTwo.topAnchor.constraint(equalTo: labelOne.bottomAnchor).isActive = true
labelTwo.trailingAnchor.constraint(equalTo: labelView.trailingAnchor).isActive = true
labelTwo.leadingAnchor.constraint(equalTo: labelOne.leadingAnchor).isActive = true
labelTwo.bottomAnchor.constraint(equalTo: labelView.bottomAnchor).isActive = true
}
func createLabel(text: String) -> UILabel {
let label = UILabel(frame: .zero)
label.text = text
label.font = UIFont.init(name: "Arial-BoldMT", size: 60)
label.textColor = .white
label.textAlignment = .right
label.contentMode = .right
label.minimumScaleFactor = 0.1
label.adjustsFontSizeToFitWidth = true
label.numberOfLines = 0
label.translatesAutoresizingMaskIntoConstraints = false
return label
}
func createButton(text: String) -> UIButton {
let button = UIButton(type: .custom)
button.setTitle(text, for: .normal)
button.setTitleColor(.white, for: .normal)
button.layer.borderColor = UIColor.white.cgColor
button.layer.borderWidth = 1
button.titleLabel?.font = UIFont.init(name: "Arial-BoldMT", size: 60)
button.titleLabel?.minimumScaleFactor = 0.1
button.titleLabel?.adjustsFontSizeToFitWidth = true
button.titleLabel?.translatesAutoresizingMaskIntoConstraints = false
button.titleLabel?.leadingAnchor.constraint(equalTo: button.leadingAnchor).isActive = true
button.titleLabel?.trailingAnchor.constraint(equalTo: button.trailingAnchor).isActive = true
button.titleLabel?.topAnchor.constraint(equalTo: button.topAnchor).isActive = true
button.titleLabel?.bottomAnchor.constraint(equalTo: button.bottomAnchor).isActive = true
button.titleLabel?.textAlignment = .center
button.titleLabel?.contentMode = .scaleAspectFill
button.titleLabel?.numberOfLines = 0
return button
}
func setButtonStackView() {
for _ in 1...5 {
let stackView = UIStackView(axis: .horizontal, distribution: .fillEqually)
for _ in 1...4 {
let button = createButton(text: "0")
button.backgroundColor = .brown
stackView.addArrangedSubview(button)
}
landscapeStackView.addArrangedSubview(stackView)
}
for _ in 1...5 {
let stackView = UIStackView(axis: .horizontal, distribution: .fillEqually)
for _ in 1...4 {
let button = createButton(text: "0")
button.backgroundColor = .purple
stackView.addArrangedSubview(button)
}
portraitStackView.addArrangedSubview(stackView)
}
subStackView.addArrangedSubview(landscapeStackView)
subStackView.addArrangedSubview(portraitStackView)
mainStackView.addArrangedSubview(subStackView)
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
if UIDevice.current.orientation.isLandscape && landscapeStackView.isHidden == true {
self.landscapeStackView.isHidden = false
}
if UIDevice.current.orientation.isPortrait && landscapeStackView.isHidden == false {
self.landscapeStackView.isHidden = true
}
self.layoutIfNeeded()
}
}
【问题讨论】:
标签: swift autolayout uilabel autoresize uistackview