iOS自動布局-筆記

iOS自動布局

個人Github博客卡啰,求關(guān)注

1 autoresizing

    autoresizingMask:創(chuàng)建視圖的同時給出其相對于父視圖的“對齊方式與縮放系數(shù)”静稻。當父視圖發(fā)生變化時,通過每個子視圖的autoresizingMask即可自動得出新的位置匈辱,而無需開發(fā)者提供振湾。

缺點:

  • 其描述界面變化規(guī)則不夠靈活,很多變化規(guī)則根本無法精確描述亡脸。autoresizingMask縮放比例是UIKit內(nèi)部計算的押搪,開發(fā)者無法指定縮放比例的精確值。
  • 變化規(guī)則只能基于父視圖與子視圖之間浅碾,無法建立同級視圖或者跨級視圖之間的關(guān)系嵌言。

樣例:

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 200)];
        containerView.backgroundColor = [UIColor blueColor];
        [self.view addSubview:containerView];
    
        UILabel *text = [[UILabel alloc] initWithFrame:CGRectZero];
        text.text = @"1231312";
        [containerView addSubview:text];
        text.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth;
        text.frame = CGRectMake(0, 0, containerView.bounds.size.width - 20, 100);
    
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
          containerView.frame = CGRectMake(0, 0, 300, 200);
          NSLog(@"%@ %@ %@ %@", @(text.frame.origin.x), @(text.frame.origin.y), @(text.frame.size.width),
                @(text.frame.size.height));
        });
    }

2 autolayout

autolayout:它允許開發(fā)者在界面上的任意兩個視圖之間建立精確的線性變化規(guī)則。所謂線性變化就是數(shù)學中的一次函數(shù)及穗,即:y = m*x + c,其中x和y是界面中任意兩個視圖的某個布局屬性,m為比例系數(shù)绵载,c為常量埂陆。每個線性變化規(guī)則稱之為布局約束(Layout Constraint)。

2.1 NSLayoutConstraint

    NS_CLASS_AVAILABLE_IOS(6_0)
    @interface NSLayoutConstraint : NSObject
    ...
    @property (readonly, assign) id firstItem;
    @property (readonly) NSLayoutAttribute firstAttribute;
    @property (readonly) NSLayoutRelation relation;
    @property (readonly, assign) id secondItem;
    @property (readonly) NSLayoutAttribute secondAttribute;
    @property (readonly) CGFloat multiplier;
    @property CGFloat constant;
    ...
    +(instancetype)constraintWithItem:(id)firstItem attribute:(NSLayoutAttribute)firstAttribute 
     relatedBy:(NSLayoutRelation)relation 
     toItem:(id)secondItem attribute:(NSLayoutAttribute)secondAttribute 
     multiplier:(CGFloat)multiplier constant:(CGFloat)constant;

公式:firstItem.firstAttribute {==,<=,>=} secondItem.secondAttribute * multiplier + constant

解釋:firstItem與secondItem分別是界面中受約束的視圖與被參照的視圖娃豹。他們不一定非得是兄弟關(guān)系或者父子關(guān)系焚虱,只要是他們有著共同的祖先視圖即可,這一點是autoresizingMask無法做到的懂版。
fir

stAttribute與secondAttribute分別是firstItem與secondItem的某個布局屬性(NSLayoutAttribute)鹃栽。注意,firstItem與secondItem不一定非得是同樣的值躯畴,允許定義諸如某視圖的高度等于另一個視圖的寬度這樣的約束
民鼓。NSLayoutAttributeNotAnAttribute這個額外解釋一下薇芝,當我們需要為某個視圖精確指定一個寬度或者高度值時,這時候secondItem為nil丰嘉,secondAttribute為NSLayoutAttributeNotAnAttribute夯到。relation定義了布局關(guān)系(NSLayoutRelation)。

    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
        UIView *v1 = [UIView new];
        v1.backgroundColor = [UIColor blueColor];
        v1.translatesAutoresizingMaskIntoConstraints = NO;
        [self.view addSubview:v1];
        
        
        NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:v1
                                                                         attribute:NSLayoutAttributeTop
                                                                         relatedBy:NSLayoutRelationEqual
                                                                            toItem:self.view
                                                                         attribute:NSLayoutAttributeTop
                                                                        multiplier:1
                                                                          constant:0];
        NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:v1
                                                                          attribute:NSLayoutAttributeLeft
                                                                          relatedBy:NSLayoutRelationEqual
                                                                             toItem:self.view
                                                                          attribute:NSLayoutAttributeLeft
                                                                         multiplier:1
                                                                           constant:0];
        NSLayoutConstraint *rightConstraint = [NSLayoutConstraint constraintWithItem:v1
                                                                           attribute:NSLayoutAttributeRight
                                                                           relatedBy:NSLayoutRelationEqual
                                                                              toItem:self.view
                                                                           attribute:NSLayoutAttributeRight
                                                                          multiplier:1
                                                                            constant:0];
        NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:v1
                                                                            attribute:NSLayoutAttributeHeight
                                                                            relatedBy:NSLayoutRelationEqual
                                                                               toItem:self.view
                                                                            attribute:NSLayoutAttributeHeight
                                                                           multiplier:0.5
                                                                             constant:0];
        // iOS8 以下
    //    [v1 addConstraint:topConstraint];
    //    [v1 addConstraint:leftConstraint];
    //    [v1 addConstraint:rightConstraint];
    //    [v1 addConstraint:heightConstraint];
        // iOS8及以上
        topConstraint.active = YES;
        leftConstraint.active = YES;
        rightConstraint.active = YES;
        heightConstraint.active = YES;
    }

2.2 VFL

2.3 自身內(nèi)容尺寸約束饮亏、修改約束耍贾、布局動畫

    自身內(nèi)容尺寸約束:一般來說,要確定一個視圖的精確位置路幸,至少需要4個布局約束(以確定水平位置x荐开、垂直位置y、寬度w和高度h)简肴。但是晃听,某些用來展現(xiàn)內(nèi)容的用戶控件,例如文本控件UILabel着帽、按鈕UIButton杂伟、圖片視圖UIImageView等域那,它們具有自身內(nèi)容尺寸(Intrinsic Content Size)墓律,此類用戶控件會根據(jù)自身內(nèi)容尺寸添加布局約束。也就是說胃夏,如果開發(fā)者沒有顯式給出其寬度或者高度約束予借,則其自動添加的自身內(nèi)容約束將會起作用越平。因此看似“缺失”約束,實際上并非如此灵迫。

對于約束的如下幾個重要屬性:

    @property (readonly, assign) id firstItem;
    @property (readonly) NSLayoutAttribute firstAttribute;
    @property (readonly) NSLayoutRelation relation;
    @property (readonly, assign) id secondItem;
    @property (readonly) NSLayoutAttribute secondAttribute;
    @property (readonly) CGFloat multiplier;
        
    /* Unlike the other properties, the constant may be modified after constraint creation.  Setting the constant on an existing constraint performs much better than removing the constraint and adding a new one that's just like the old but for having a new constant.
     */
    @property CGFloat constant;

更新約束

當使用代碼來修改約束時秦叛,只能修改約束的常量值constant。一旦創(chuàng)建了約束瀑粥,其他只讀屬性都是無法修改的挣跋,特別要注意的是比例系數(shù)multiplier也是只讀的。

添加刪除約束

    - (void)keyboardWillShow:(NSNotification *)notification
    {
        self.labelCenterYNormalCons.active = NO;
        self.labelCenterYKeyboardCons.active = YES;
    }
    
    - (void)keyboardWillHide:(NSNotification *)notification
    {
        self.labelCenterYKeyboardCons.active = NO;
        self.labelCenterYNormalCons.active = YES;
    }

盡量先設(shè)置需要將active置為NO的約束狞换,然后再設(shè)置需要將active置為YES的約束避咆,如果顛倒上面兩條語句的話,可能會引起運行時約束錯誤修噪。

修改約束優(yōu)先級

    - (void)keyboardWillShow:(NSNotification *)notification
    {
        self.labelCenterYNormalCons.priority = UILayoutPriorityDefaultLow;
        self.labelCenterYKeyboardCons.priority = UILayoutPriorityDefaultHigh;
    }
    
    - (void)keyboardWillHide:(NSNotification *)notification
    {
        self.labelCenterYKeyboardCons.priority = UILayoutPriorityDefaultLow;
        self.labelCenterYNormalCons.priority = UILayoutPriorityDefaultHigh;
    }

需要注意的是查库,只能修改可選約束的優(yōu)先級,也就是說:

  • 不允許將優(yōu)先級由小于1000的值改為1000
  • 不允許將優(yōu)先級由1000修改為小于1000的值

例如黄琼,如果將優(yōu)先級由250修改為1000樊销,則會拋出異常。

自身內(nèi)容尺寸約束的抗擠壓與抗拉抻效果

彈簧會有自身固有長度,當有外力作用時围苫,彈簧會抵抗外力作用裤园,盡量接近固有長度。

抗拉抻:當外力拉長彈簧時够吩,彈簧長度大于固有長度比然,且產(chǎn)生向內(nèi)收的力阻止外力拉抻,且盡量維持長度接近自身固有長度周循。 
抗擠壓:當外力擠壓彈簧時强法,彈簧長度小于固有長度,且產(chǎn)生向外頂?shù)牧ψ柚雇饬D壓湾笛,且盡量維持長度接近自身固有長度饮怯。

對于自身內(nèi)容尺寸約束,Hug值表示抗拉抻優(yōu)先級嚎研,CompressionResistance值表示抗壓縮優(yōu)先級蓖墅。Hug值越高越難被拉抻,CompressionResistance值越高越難被壓縮临扮。這兩個都是針對自身內(nèi)容尺寸论矾。這兩個值越高,在自動布局的時候杆勇,view的真實布局就越接近自身內(nèi)容尺寸贪壳。他們表達的是一種自身內(nèi)容尺寸約束對外加約束的抵抗力。

參考文檔:

  1. iOS 8 Auto Layout界面自動布局系列1-自動布局的基本原理
  2. iOS 8 Auto Layout界面自動布局系列2-使用Xcode的Interface Builder添加布局約束
  3. iOS 8 Auto Layout界面自動布局系列3-使用代碼添加布局約束
  4. iOS 8 Auto Layout界面自動布局系列4-使用VFL添加布局約束
  5. iOS 8 Auto Layout界面自動布局系列5-自身內(nèi)容尺寸約束蚜退、修改約束闰靴、布局動畫
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市钻注,隨后出現(xiàn)的幾起案子蚂且,更是在濱河造成了極大的恐慌,老刑警劉巖幅恋,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杏死,死亡現(xiàn)場離奇詭異,居然都是意外死亡捆交,警方通過查閱死者的電腦和手機淑翼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來零渐,“玉大人,你說我怎么就攤上這事系忙∷信危” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長风宁。 經(jīng)常有香客問我洁墙,道長,這世上最難降的妖魔是什么戒财? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任热监,我火速辦了婚禮,結(jié)果婚禮上饮寞,老公的妹妹穿的比我還像新娘孝扛。我一直安慰自己,他們只是感情好幽崩,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布苦始。 她就那樣靜靜地躺著,像睡著了一般慌申。 火紅的嫁衣襯著肌膚如雪陌选。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天蹄溉,我揣著相機與錄音咨油,去河邊找鬼。 笑死柒爵,一個胖子當著我的面吹牛役电,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播餐弱,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼宴霸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了膏蚓?” 一聲冷哼從身側(cè)響起瓢谢,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎驮瞧,沒想到半個月后氓扛,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡论笔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年采郎,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狂魔。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡蒜埋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出最楷,到底是詐尸還是另有隱情整份,我是刑警寧澤待错,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站烈评,受9級特大地震影響火俄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜讲冠,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一瓜客、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧竿开,春花似錦谱仪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至胳搞,卻和暖如春卸例,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背肌毅。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工筷转, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人悬而。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓呜舒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親笨奠。 傳聞我的和親對象是個殘疾皇子袭蝗,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345

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