找到masonry結合view animation要這樣處理的原因了,參考文章在此:
http://www.lxweimin.com/p/eb2c4bb4e3f1
學習的深度還是需要自己去堅持!
(1)情景:
自定義一個類似如下的組件:
效果要類似原生action sheet的動效,支持數據源構建對應ui,同時要有交互的輸出。
(2)問題
構建途中,仍然習慣使用masonry布局,思路是先根據數據源構建對應ui,待用戶觸發出現交互時彈出ui。
我這里首先將構建的ui置于屏幕外底部,alpha = 0,觸發交互后,利用基礎動畫形成彈出效果。但是這種直接構建UI,然后在使用基礎動畫彈出的效果是錯亂的,排除約束等位置信息可能的錯誤之后,決定用frame實現,frame果然沒有問題。
(3)解決
參考網上資料,各種方法中,有的說要使用
[view.superView layoutIfNeeded];
重新設置layout屬性時,應該調這個方法。但是我是調用基礎動畫,block中進行masonry的remake,按理說是可以進行約束更新的,不需要layoutIfNeeded,這是疑問1.
按照網上說法重新設置之后還是有錯亂現象,然后又找資料,說是需要延遲處理,最后在調用動畫出現的方法前加了一段小時間的延遲,masonry 的remake在延遲方法中, layoutIfNeeded在基礎動畫的block中達到了預期效果。
//更新約束
[self.cancelButton mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self).offset(15 * WidthScale);
make.right.equalTo(self).offset(- 15 * WidthScale);
make.height.mas_equalTo(44 * HEIGHT_SCALE);
make.bottom.equalTo(self).offset(- 15 * HEIGHT_SCALE);
}];
//使約束動畫效果出現
[UIView animateWithDuration:0.25 animations:^{
[self.cancelButton.superview layoutIfNeeded];
}];
(4)思考
考慮到masonry的約束添加和更改與基礎動畫的動畫實現都是在block中完成的,所以不會立即執行的。當第一次進行約束后,直接不延遲掉更改的約束動畫,就很容易造成約束未定動畫開始的現象。所以需要延遲執行;約束更改的語句是放在基礎動畫block之外的,block中只有layoutIfNeeded進行控件約束更新,這一點也是由于masonry的更新約束在block中而采用的方法,layoutIfNeeded相當于直接順序執行改變約束了(我的思考)。