LayoutAnchor - ShenYj/ShenYj.github.io GitHub Wiki
NSLayoutAnchor 作为 iOS9 的新特性是对AutoLayout创建约束的补充,核心还是 NSLayoutConstraint,可以避免过长创建约束代码
早期一条条创建 NSLayoutConstraint 约束的方式的确太啰嗦,因此绝大部分iOS 开发者应该都是使用 Masonry/SnapKit 或其他成熟的库来实现代码布局
简单的布局,也有使用 NSLayoutAnchor 实现过,不过一直没有研究过更新布局的方式,今天有空,换成原生的API,试一下最常见的两种情形下更新布局的实现
-
示例代码,每一次点击按钮的时候,更改红色View的宽度
import UIKit class ViewController: UIViewController { private lazy var testButton = { let btn = UIButton() btn.setTitle("test", for: .normal) btn.setTitleColor(.black, for: .normal) btn.backgroundColor = UIColor.systemGreen btn.layer.cornerRadius = 10 btn.layer.maskedCorners = [.layerMinXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMinYCorner, .layerMaxXMaxYCorner] btn.layer.masksToBounds = true btn.translatesAutoresizingMaskIntoConstraints = false btn.addTarget(self, action: #selector(_target(_:)), for: .touchUpInside) return btn }() private lazy var redView = { let v = UIView() v.backgroundColor = UIColor.systemRed v.layer.cornerRadius = 10 v.layer.maskedCorners = [.layerMinXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMinYCorner, .layerMaxXMaxYCorner] v.layer.masksToBounds = true v.translatesAutoresizingMaskIntoConstraints = false return v }() private var feedback: UIImpactFeedbackGenerator? private var widthAnchorConstrainst: NSLayoutConstraint? override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. view.backgroundColor = .systemBlue view.addSubview(testButton) view.addSubview(redView) NSLayoutConstraint.activate([ redView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 40), redView.centerXAnchor.constraint(equalTo: view.centerXAnchor), redView.heightAnchor.constraint(equalToConstant: 200), testButton.topAnchor.constraint(equalTo: redView.bottomAnchor, constant: 40), testButton.widthAnchor.constraint(equalToConstant: 120), testButton.centerXAnchor.constraint(equalTo: view.centerXAnchor), testButton.heightAnchor.constraint(equalToConstant: 44) ]) widthAnchorConstrainst = redView.widthAnchor.constraint(equalToConstant: 200) widthAnchorConstrainst?.isActive = true } @objc private func _target(_ sender: UIButton) { if widthAnchorConstrainst?.constant == 200 { widthAnchorConstrainst?.constant = 100 } else { widthAnchorConstrainst?.constant = 200 } } }
-
示例代码,每一次点击按钮的时候,更改按钮的相对位置
import UIKit class ViewController: UIViewController { private lazy var testButton = { let btn = UIButton() btn.setTitle("test", for: .normal) btn.setTitleColor(.black, for: .normal) btn.backgroundColor = UIColor.systemGreen btn.layer.cornerRadius = 10 btn.layer.maskedCorners = [.layerMinXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMinYCorner, .layerMaxXMaxYCorner] btn.layer.masksToBounds = true btn.translatesAutoresizingMaskIntoConstraints = false btn.addTarget(self, action: #selector(_target(_:)), for: .touchUpInside) return btn }() private lazy var redView = { let v = UIView() v.backgroundColor = UIColor.systemRed v.layer.cornerRadius = 10 v.layer.maskedCorners = [.layerMinXMinYCorner, .layerMinXMaxYCorner, .layerMaxXMinYCorner, .layerMaxXMaxYCorner] v.layer.masksToBounds = true v.translatesAutoresizingMaskIntoConstraints = false return v }() private var feedback: UIImpactFeedbackGenerator? private var buttonTopConstraint: NSLayoutConstraint? override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. view.backgroundColor = .systemBlue view.addSubview(testButton) view.addSubview(redView) NSLayoutConstraint.activate([ redView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 40), redView.centerXAnchor.constraint(equalTo: view.centerXAnchor), redView.heightAnchor.constraint(equalToConstant: 200), redView.widthAnchor.constraint(equalToConstant: 200), testButton.widthAnchor.constraint(equalToConstant: 120), testButton.centerXAnchor.constraint(equalTo: view.centerXAnchor), testButton.heightAnchor.constraint(equalToConstant: 44) ]) buttonTopConstraint = testButton.topAnchor.constraint(equalTo: redView.bottomAnchor, constant: 40) buttonTopConstraint?.isActive = true } @objc private func _target(_ sender: UIButton) { guard let buttonTopConstraint else { return } if let secondItem = buttonTopConstraint.secondItem as? UIView , secondItem == redView { NSLayoutConstraint.deactivate([buttonTopConstraint]) self.buttonTopConstraint = testButton.topAnchor.constraint(equalTo: view.centerYAnchor, constant: 0) self.buttonTopConstraint?.isActive = true } else { NSLayoutConstraint.deactivate([buttonTopConstraint]) self.buttonTopConstraint = testButton.topAnchor.constraint(equalTo: redView.bottomAnchor, constant: 40) self.buttonTopConstraint?.isActive = true } } }