这个问题纠结了我挺长时间的。一直以为把约束直接添加到动画里面就可以了。但是并没那么简单。-.-其实还是挺简
class ViewController: UIViewController { @IBOutlet weak var usernameOutlet: UITextField! @IBOutlet weak var animateBtn: UIButton! let boxView = UIView() var topConstraint: Constraint? = nil @IBAction func animateBtnClick(sender: UIButton) { UIView.animateWithDuration(5) { self.boxView.snp_updateConstraints(closure: { (make) -> Void in make.top.equalTo(self.view).offset(30) }) self.view.layoutIfNeeded() // self.view.setNeedsDisplay() // self.view.setNeedsLayout() // self.view.layoutSubviews() } } override func viewDidLoad() { super.viewDidLoad() let tapGesture = UITapGestureRecognizer(target: self, action: "tapBg:") view.addGestureRecognizer(tapGesture) boxView.backgroundColor = UIColor.purpleColor() self.view.addSubview(boxView) boxView.snp_makeConstraints { (make) -> Void in self.topConstraint = make.top.equalTo(self.view).offset(400).constraint make.left.equalTo(self.view).offset(50) make.size.equalTo(CGSize( 80, height: 80)) } } }
对于这个layoutIfNeeded, 还有一个地方我们经常会碰到,就是设置约束我们如何才能立马得到frame的数值:
view.superview. layoutIfneed()
今天要谈的重点来了, iOS layout 相关机制
- (CGSize)sizeThatFits:(CGSize)size - (void)sizeToFit - (void)layoutSubviews - (void)lauoutIfNeeded - (void)setNeedsLayout - (void)setNeedsDisplay - (void)drawRect
1. layoutSubviews:
- init 不会触发
- addsubview 会触发
- 设置view的frame(有变化的)
- 滚动一个UIScroollView会
- 旋转Screen,触发父UIView上的layoutSubViews事件
- 直接调用setLayoutSubviews
- 直接调用setNeedsLayout
You should override this method only if the autoresizing behaviors of the subviews do not offer the behavior you want. // layoutSubviews, 当我们在某个类的内部调整子视图位置时,需要调用。
刷新子对象布局:
- layoutSubviews: 不做任何事情,需要重写
- setNeedsLayout: 标记为需要重新布局,异步调用layoutIfNeeded刷新布局,不立即刷新,但是layoutSubviews一定会被调用
- layoutIfNeeded: 如果有需要刷新新的标记,立即调用layoutSubviews进行布局
如果需要立即刷新,需要先view.setNeedsLayout()(设置标记),然后调用view.layoutIfneeded()立即刷新