Есть несколько способов добиться этого, но здесь вам не хватает некоторой ключевой информации о том, как настраивается ваш макет.
Я предполагаю, что 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()
}
}
}