有几种方法可以实现这一点,但您在这里缺少的是有关如何设置布局的一些关键信息。
我会假设您拥有的 3 个视图是垂直对齐的,彼此相邻且宽度相等。
以编程方式,我们从水平角度看到的内容已完成:
let firstLeading = NSLayoutConstraint(item: view1, attribute: .leading, relatedBy: .equal, toItem: parent, attribute: .leading, multiplier: 1.0, constant: 0.0)
let betweenSecondAndFirst = NSLayoutConstraint(item: view2, attribute: .leading, relatedBy: .equal, toItem: view1, attribute: .trailing, multiplier: 1.0, constant: 0.0)
let secondEqualWidth = NSLayoutConstraint(item: view2, attribute: .width, relatedBy: .equal, toItem: view1, attribute: .width, multiplier: 1.0, constant: 0.0)
let betweenThirdAndSecond = NSLayoutConstraint(item: view3, attribute: .leading, relatedBy: .equal, toItem: view2, attribute: .trailing, multiplier: 1.0, constant: 0.0)
let lastEqualWidth = NSLayoutConstraint(item: view3, attribute: .width, relatedBy: .equal, toItem: view1, attribute: .width, multiplier: 1.0, constant: 0.0) // Note to view1 to make things easier
let lastTrailing = NSLayoutConstraint(item: view3, attribute: .trailing, relatedBy: .equal, toItem: parent, attribute: .trailing, multiplier: 1.0, constant: 0.0)
当第二个被跳过时,我们可以简单地禁用betweenThirdAndSecond 并将betweenThirdAndFirst 添加为:
let betweenThirdAndFirst = NSLayoutConstraint(item: view3, attribute: .leading, relatedBy: .equal, toItem: view1, attribute: .trailing, multiplier: 1.0, constant: 0.0)
您可以使用约束上的属性来启用或禁用它们。或者您可以简单地使用优先级并将它们从 900 切换到 100。您实际上可以在情节提要中设置所有这些约束,然后将 2 作为插座拖到您的代码中。然后只需:
func setMiddleViewShown(_ shown: Bool) {
UIView.animate(withDuration: 0.3) {
self.betweenThirdAndSecond.priority = UILayoutPriority(rawValue: shown ? 900.0 : 100.0)
self.betweenThirdAndFirst.priority = UILayoutPriority(rawValue: shown ? 100.0 : 900.0)
self.view2.alpha = shown ? 1.0 : 0.0
parent.layoutIfNeeded() // parent is most likely "self.view"
}
}
这种方式可能是您可以控制的最佳方式(主要是动画)。但是您也可以使用UIStackView,它具有插入或删除视图的方法。 UICollectionView 也应该可以工作。或者您知道.. 只需以编程方式完成所有操作,忽略约束,只需为每个视图设置 frame。
在使用UIStackView 时,我能想到的最低要求如下:
class ViewController: UIViewController {
let views: [UIView] = [
{ let view = UIView(); view.backgroundColor = .red; return view; }(),
{ let view = UIView(); view.backgroundColor = .green; return view; }(),
{ let view = UIView(); view.backgroundColor = .blue; return view; }()
]
lazy var stackView: UIStackView = {
let stackView = UIStackView(frame: CGRect(x: 50.0, y: 100.0, width: 300.0, height: 200.0))
self.view.addSubview(stackView)
stackView.backgroundColor = .black
stackView.distribution = .fillEqually
return stackView
}()
override func viewDidLoad() {
super.viewDidLoad()
stackView.addArrangedSubview(views[0])
stackView.addArrangedSubview(views[1])
stackView.addArrangedSubview(views[2])
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
UIView.animate(withDuration: 0.3) {
if self.stackView.arrangedSubviews.count == 3 {
self.views[1].alpha = 0.0
self.stackView.removeArrangedSubview(self.views[1])
} else {
self.views[1].alpha = 1.0
self.stackView.insertArrangedSubview(self.views[1], at: 1)
}
self.stackView.layoutIfNeeded()
}
}
}