Autolayout和Frame

現(xiàn)在iOS頁面布局用的最多的就是Frame和Autolayout,在Autolayout通過Masonry封裝在實際使用中也十分方便叫惊。實際上,Autolayout的約束最后都是系統(tǒng)最終轉(zhuǎn)化成frame來進行布局的,對與一個View來說轴踱,最終確定其中心點位置和View的寬高埃元。當Autolayout和Frame設(shè)置上產(chǎn)生沖突的時候涝涤,則會以Autolayout的設(shè)置為準。這篇主要討論布局中常用的幾個方法和autolayout遇到動畫的情形岛杀。

跟布局相關(guān)的方法

- (void)setNeedsLayout;
- (void)layoutIfNeeded;
- (void)layoutSubviews;

setNeedsLayout方法標記當前view是需要重新布局的阔拳,在下一次runloop中,進行重新布局类嗤。如果說想在當前runloop中立刻更新布局糊肠,則通過調(diào)用layoutIfNeeded方法可以實現(xiàn),此時系統(tǒng)會調(diào)用layoutSubviews遗锣。在layoutSubviews方法中货裹,可以自己定義新的view或者改變子view的布局。

Autolayout相關(guān)的方法

//view的方法
- (void)updateConstraintsIfNeeded;
//重寫view中的方法
- (void)updateConstraints
- (BOOL)needsUpdateConstraints
- (void)setNeedsUpdateConstraints
  
//重寫viewController中的方法
- (void)updateViewConstraints

setNeedsUpdateConstraints只是標記當前view的約束需要在下一次runloop中更新精偿,updateConstraintsIfNeeded如果過滿足更新條件會立刻調(diào)用updateConstraints來更新約束弧圆,updateConstraints是子view需要重寫的方法,來更新View的約束笔咽,最后需要調(diào)用[super updateConstraints]搔预,否則會崩。而updateViewConstraints是定義在viewController中的拓轻,方便去更新viewController對應(yīng)view的約束斯撮。

具體可以通過調(diào)用view的setNeedsUpdateConstraints來最終調(diào)用到viewController的updateViewConstraints方法來,如果沒有這個方法扶叉,那么每次都要定義一個子view去重寫updateConstraints方法會比較繁瑣勿锅。updateConstraints和updateViewConstrains方法可以把約束的代碼和和業(yè)務(wù)邏輯分開帕膜,另外性能也更好。

為什么會有setxxxxx和xxxifNeeded方法

setxxxxx方法可能是為了性能溢十,沒有在代碼更新布局或者約束之后立刻執(zhí)行垮刹,而是在下一次runloop中執(zhí)行。

xxxxIfNeeded方法則是為了在必要的時候张弛,立刻更新約束或者布局荒典,舉個例子,有些時候同時使用動畫和autolayout吞鸭。

Autolayout和動畫

現(xiàn)在實現(xiàn)一個view滑動的動畫:

@interface MyView : UIView
 
-(void)layoutSubviews;
@end
@implementation MyView
 
-(void)layoutSubviews
{
    [super layoutSubviews];
}
@end
- (void)viewDidLoad {
 
    [super viewDidLoad];
 
   
    _container = [[MyView alloc] initWithFrame:self.view.frame];
 
    [self.view addSubview:_container];
 
     
    _redView = [[MyView alloc] initWithFrame:CGRectMake(100, 100, 100, 50)];
 
    _redView.backgroundColor = [UIColor redColor];
 
    [_container addSubview:_redView];
 
    [_redView mas_makeConstraints:^(MASConstraintMaker *make) {
 
        make.centerX.equalTo(self.view);
 
        make.centerY.equalTo(self.view);
 
        make.width.height.equalTo(@100);
 
    }];
 
     
 
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
 
    btn.titleLabel.text = @"點擊動畫";
 
    btn.backgroundColor = [UIColor greenColor];
 
    [_container addSubview:btn];
 
    [btn mas_makeConstraints:^(MASConstraintMaker *make) {
 
        make.centerX.equalTo(self.view);
 
        make.centerY.equalTo(self.view).offset(100);
 
        make.width.equalTo(@100);
 
        make.height.equalTo(@50);
 
    }];
 
    [btn addTarget:self action:@selector(onButtonClick:) forControlEvents:
    UIControlEventTouchUpInside];
 
} 

使用frame

- (void)onButtonClick:(id)sender
 
{
    [UIView animateWithDuration:1 animations:^{
 
        self.redView.frame = CGRectMake(0, self.redView.frame.origin.y, self.
            redView.frame.size.width, self.redView.frame.size.height);
 
    }];
}

和預(yù)期結(jié)果一致寺董,紅色的view滑動到屏幕的最左側(cè)。

使用autolayout

- (void)onButtonClick:(id)sender
 
{
    [UIView animateWithDuration:1 animations:^{
    [self.redView mas_remakeConstraints:^(MASConstraintMaker *make) {
 
        make.width.height.equalTo(@100);
 
        make.left.centerY.equalTo(self.view);
 
    }];
}

和預(yù)期的結(jié)果不一致刻剥,紅色的view突然一下移動到屏幕的最左側(cè)遮咖,上面這種做法是有問題的,現(xiàn)在在動畫的block中添加一行日志的代碼造虏。

- (void)onButtonClick:(id)sender
{
    [UIView animateWithDuration:1 animations:^{
        [self.redView mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.width.height.equalTo(@100);
            make.left.centerY.equalTo(self.view);
        }];
        NSLog(@"redView x = %@", @(self.redView.frame.origin.x));
    }];
}

輸出日志:

2016-09-07 17:44:03.069 2323[99216:10267632] redView x = 137.5(原來的位置)

說明在重新更新紅色View的約束之后御吞,系統(tǒng)并沒有立刻轉(zhuǎn)化成對應(yīng)的frame值,還是原來的位置漓藕,但是為什么view會移動到屏幕最右側(cè)而不是靜止呢陶珠。

因為系統(tǒng)在計算動畫插值的過程中,發(fā)現(xiàn)紅色view的前后的位置是一樣的享钞,最后的結(jié)果就是在原地靜止揍诽,猜測有可能系統(tǒng)為了優(yōu)化直接取消了動畫。這是在當前runloop發(fā)生的邏輯嫩与,在下一次runloop過程中寝姿,上一次給紅色view設(shè)置的約束就生效了,系統(tǒng)會將約束更新到frame的表現(xiàn)上划滋,所以紅色view直接跑到了屏幕最左側(cè)饵筑。

現(xiàn)在的問題是需要在系統(tǒng)計算動畫插值的時候,將視圖的frame即時的更新处坪,所以調(diào)用紅色view的layoutIfNeeded方法就好了根资。

- (void)onButtonClick:(id)sender
{
    [UIView animateWithDuration:1 animations:^{
        [self.redView mas_remakeConstraints:^(MASConstraintMaker *make) {
 
            make.width.height.equalTo(@100);
 
            make.left.centerY.equalTo(self.view);
 
        }];
 
        NSLog(@"redView x = %@", @(self.redView.frame.origin.x));
 
        [self.container layoutIfNeeded];
 
        NSLog(@"redView x = %@", @(self.redView.frame.origin.x));
 
    }];
}

日志輸出為:

2016-09-07 17:50:33.297 2323[99250:10270639] redView x = 137.5
 
2016-09-07 17:50:33.299 2323[99250:10270639] redView x = 0

通過對比可以看到,在調(diào)用parentView的layoutIfNeeded之后同窘,其frame得到更新了玄帕,所以最后動畫如預(yù)期一樣出現(xiàn)了。這里必須是調(diào)用parentView的layoutIfNeeded方法想邦,調(diào)用紅色視圖的layoutIfNeeded方法是不會更新它自己的frame的裤纹。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者丧没。
  • 序言:七十年代末鹰椒,一起剝皮案震驚了整個濱河市锡移,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌漆际,老刑警劉巖淆珊,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異奸汇,居然都是意外死亡施符,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門擂找,熙熙樓的掌柜王于貴愁眉苦臉地迎上來戳吝,“玉大人,你說我怎么就攤上這事婴洼」强樱” “怎么了撼嗓?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵柬采,是天一觀的道長。 經(jīng)常有香客問我且警,道長粉捻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任斑芜,我火速辦了婚禮肩刃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘杏头。我一直安慰自己盈包,他們只是感情好,可當我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布醇王。 她就那樣靜靜地躺著呢燥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪寓娩。 梳的紋絲不亂的頭發(fā)上叛氨,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天,我揣著相機與錄音棘伴,去河邊找鬼寞埠。 笑死,一個胖子當著我的面吹牛焊夸,可吹牛的內(nèi)容都是我干的仁连。 我是一名探鬼主播,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼阱穗,長吁一口氣:“原來是場噩夢啊……” “哼饭冬!你這毒婦竟也來了帅容?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤伍伤,失蹤者是張志新(化名)和其女友劉穎并徘,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扰魂,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡麦乞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了劝评。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片姐直。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蒋畜,靈堂內(nèi)的尸體忽然破棺而出声畏,到底是詐尸還是另有隱情,我是刑警寧澤姻成,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布插龄,位于F島的核電站,受9級特大地震影響科展,放射性物質(zhì)發(fā)生泄漏均牢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一才睹、第九天 我趴在偏房一處隱蔽的房頂上張望徘跪。 院中可真熱鬧,春花似錦琅攘、人聲如沸垮庐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽哨查。三九已至,卻和暖如春置济,著一層夾襖步出監(jiān)牢的瞬間解恰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工浙于, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留护盈,地道東北人。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓羞酗,卻偏偏與公主長得像腐宋,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,629評論 2 354

推薦閱讀更多精彩內(nèi)容