问题
I would like to create a menu like android in iOS. I'm using layout constraints to setup constraints. I'm facing the issue when I'm trying to update the left constraint of an image on button click (It should animate to clicked button's position). Can anyone help me? It should support landscape and portrait.
I don't want to user third party code and don't want to use the NSLayoutconstraint
.
Here is my code.
class MenuViewController: UIViewController {
var buttons: [UIButton] = []
var imageView : UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
addMenuItems()
}
func addMenuItems() {
for _ in 0...4 {
let button : UIButton = UIButton()
self.view.addSubview(button)
button.backgroundColor = UIColor.darkGray
button.addTarget(self, action: #selector(didSelectedButton(_:)), for: .touchUpInside)
self.buttons.append(button)
}
for (index, button) in buttons.enumerated() {
button.setTitle(" \(index)", for: .normal)
if index == 0 {
button.translatesAutoresizingMaskIntoConstraints = false
button.leftAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leftAnchor, constant: 0).isActive = true
button.widthAnchor.constraint(greaterThanOrEqualToConstant: 1).isActive = true
button.heightAnchor.constraint(equalToConstant: 50).isActive = true
button.topAnchor.constraint(equalTo: self.view.topAnchor, constant:200).isActive = true
self.imageView = UIImageView()
self.view.addSubview(self.imageView)
self.imageView.backgroundColor = UIColor.red
self.imageView.translatesAutoresizingMaskIntoConstraints = false
self.imageView.leftAnchor.constraint(equalTo: button.leftAnchor, constant: 0).isActive = true
self.imageView.widthAnchor.constraint(equalTo: button.widthAnchor, multiplier: 1).isActive = true
self.imageView.heightAnchor.constraint(equalToConstant: 4).isActive = true
self.imageView.topAnchor.constraint(equalTo: self.view.topAnchor, constant:250).isActive = true
}
else {
let preButton = buttons\[index - 1\]
button.translatesAutoresizingMaskIntoConstraints = false
button.leftAnchor.constraint(equalTo: preButton.rightAnchor, constant: 0).isActive = true
button.widthAnchor.constraint(equalTo: preButton.widthAnchor, multiplier: 1).isActive = true
button.heightAnchor.constraint(equalToConstant: 50).isActive = true
button.topAnchor.constraint(equalTo: self.view.topAnchor, constant:200).isActive = true
if index == self.buttons.count - 1 {
button.rightAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.rightAnchor, constant: 0).isActive = true
}
}
}
}
@objc func didSelectedButton(_ button:UIButton) {
UIView.animate(withDuration: 1, animations: {
self.imageView.leftAnchor.constraint(equalTo: button.leftAnchor).isActive = true
self.imageView.layoutIfNeeded()
}, completion: nil)
}
}
回答1:
Using anchors creates NSLayoutContraint
s. You need to deactivate the previous ones when you create new ones.
Add this property to your MenuViewController
:
var imageLeftConstraint: NSLayoutConstraint?
Set it when you first create the constraint:
imageLeftConstraint = self.imageView.leftAnchor.constraint(equalTo: button.leftAnchor, constant: 0)
imageLeftConstraint?.isActive = true
Then use it to deactivate the previous constraint before adding a new one:
@objc func didSelectedButton(_ button:UIButton) {
imageLeftConstraint?.isActive = false
imageLeftConstraint = self.imageView.leftAnchor.constraint(equalTo: button.leftAnchor)
imageLeftConstraint?.isActive = true
UIView.animate(withDuration: 1, animations: {
self.view.layoutIfNeeded()
}, completion: nil)
}
Note: You need to call layoutIfNeeded()
on the superView of imageView
(aka self.view
) because the constraint between button
and imageView
will be added to their common ancestor (self.view
).
来源:https://stackoverflow.com/questions/54097046/how-to-update-anchor-constraint-in-swift