1.概述:隨着iOS設備的更新迭代,屏幕適配問題也變得愈發重要,應運而生了Autolayout。在Xcode4.1和OS X10.7以後才起效。api
2.簡介:Apple提供了2種方式佈局Autolayout,用xib來佈局;另外一種利用代碼進行佈局,在Apple的sdk中提供了2個類庫:NSLayoutManager和NSLayoutConstraint。NSLayoutManager類主要是配合NSTextStorage,NSTextContainer實現NSCoding協議用來佈局text視圖,而NSLayoutConstraint類則是佈局整個視圖結構(着重介紹)。數組
3.原理:Autolayout的主要思想就是約束。在NSLayoutConstraint類中,有一個最重要的類方法xcode
+(instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;
實現的公式是"view1.attr1 = view2.attr2 * multiplier + constant".創建2個視圖之間的約束聯繫(第二視圖能夠爲nil)。可是用這個方法的簡單明瞭,缺點就是太過繁瑣複雜.可是咱們推薦使用VFL進行佈局。ide
4.1內容:佈局
1).當咱們使用Autolayout時,咱們要摒棄Xcode自動適應設置,將translatesAutoresizingMaskIntoConstraints=NO;否則會形成視圖混亂。spa
2).聽從「高內聚」的原則,在UIView.h類中系統定義了- (void)updateConstraints;在UIViewController.h類中系統定義了- (void)updateViewConstraints;Overrides must call super or send -updateConstraints to the view=>即[super updateViewConstraints];code
3).最基本的添加約束的方法:建立一個view對象,建立一個NSLayoutConstraint約束對象,constraintWithItem進行約束設置,view對象中添加約束。orm
4.2內容:對象
1).Autolayout還提供了VFL(Visual Format Language)來約束,+ (NSArray *)constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(NSDictionary *)metrics views:(NSDictionary *)views;blog
//format:傳入單獨每一個view的約束語句;查詢xcode的api的Visual Format Syntax。
2).Autolayout步驟:建立一個view,而且添加到父視圖中去顯示->[父視圖 addConstraints:(約束數組)]->傳入參數,format具體約束語句,opts可置爲nil,metrics傳入距離參數(用參數代替魔數),views傳入相應的視圖控件,metrics和views是爲format服務的。
3).例1:
- (void)updateViewConstraints{ [super updateViewConstraints];//override初始化 UIView *view1 = [[UIView alloc] init]; view1.translatesAutoresizingMaskIntoConstraints = NO;//取消自動佈局 view1.backgroundColor = [UIColor blueColor]; [self.view addSubview:view1]; NSDictionary *views_Dic = @{@"view1":view1};//約束的控件 NSString *hLayoutStr = @"H:|-(==100)-[view1(==100)]";//H:表明橫向,|表明相對於父視圖,-表明約束距離,()裏面的全部表示約束距離,[]裏面表示約束的視圖對象,這句話表示:橫向從左到右,相對於父視圖距離100像素,view1的寬爲100 NSString *vLayoutStr = @"V:|-(==100)-[view1(==50)]";//V:表明縱向,|表明相對於父視圖,-表明約束距離,()裏面的全部表示約束距離,[]裏面表示約束的視圖對象,這句話表示:縱向從上到下,相對於父視圖距離100像素,view1的高爲50 NSArray *hLayoutArr = [NSLayoutConstraint constraintsWithVisualFormat:hLayoutStr options:0 metrics:nil views:views_Dic]; NSArray *vLayoutArr = [NSLayoutConstraint constraintsWithVisualFormat:vLayoutStr options:0 metrics:nil views:views_Dic]; [self.view addConstraints:hLayoutArr]; [self.view addConstraints:vLayoutArr]; }
例2:
- (void)updateViewConstraints{ [super updateViewConstraints];//override初始化 UIView *view1 = [[UIView alloc] init]; view1.translatesAutoresizingMaskIntoConstraints = NO; view1.backgroundColor = [UIColor blueColor]; [self.view addSubview:view1]; UIView *view2 = [[UIView alloc] init]; view2.translatesAutoresizingMaskIntoConstraints = NO; view2.backgroundColor = [UIColor greenColor]; [self.view addSubview:view2]; NSDictionary *views_Dic = @{@"view1":view1,@"view2":view2}; NSDictionary *views_metrics = @{@"Top":@50,@"Right":@20}; NSString *hLayoutStr = @"H:|-(==100)-[view1(==100)]-[view2(view1)]-Right-|";//表示:從父視圖的左邊開始,約束100像素,約束view1的寬爲100像素,約束view2的寬與view1等寬,約束距離父視圖右邊的距離爲20像素。 NSString *vLayoutStr = @"V:|-(100)-[view1(==100)]-[view2(==100)]"; NSArray *hLayoutArr = [NSLayoutConstraint constraintsWithVisualFormat:hLayoutStr options:0 metrics:views_metrics views:views_Dic]; NSArray *vLayoutArr = [NSLayoutConstraint constraintsWithVisualFormat:vLayoutStr options:0 metrics:views_metrics views:views_Dic]; [self.view addConstraints:hLayoutArr];//橫向約束 [self.view addConstraints:vLayoutArr];//縱向約束 }
例3:
- (void)viewDidLoad { UIView *view_nav = [[UIView alloc] init]; view_nav.translatesAutoresizingMaskIntoConstraints = NO; view_nav.backgroundColor = [UIColorFactory colorNav]; [self.view addSubview:view_nav]; self.mUAccounts_table = [[UITableView alloc] init]; self.mUAccounts_table.delegate = self; self.mUAccounts_table.dataSource = self; self.mUAccounts_table.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:self.mUAccounts_table]; //AutoLayout進行約束 NSDictionary *views_dic = @{@"view_nav":view_nav,@"mUAccounts_table":self.mUAccounts_table}; NSDictionary *metrics_dic = @{@"Top":@0,@"Bottom":@0,@"Left":@0,@"Right":@0, @"ScreenWidth":@((float)ScreenWidth), @"tabBar_height":@(self.tabBarController.tabBar.frame.size.height), @"Table_height":@((float)ScreenHeight-64-49)}; //當等寬或者等高時,將相同方向的兩個視圖拆分紅同個方向的2個約束 [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-Left-[view_nav(ScreenWidth)]" options:NSLayoutFormatAlignAllLeft metrics:metrics_dic views:views_dic]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-Top-[view_nav(64)]-[mUAccounts_table(Table_height)]" options:0 metrics:metrics_dic views:views_dic]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[mUAccounts_table(ScreenWidth)]" options:0 metrics:metrics_dic views:views_dic]]; }
5.1注意:
1).有可能出現-(void)updateViewConstraints;不自動調用的狀況,能夠直接在viewDidLoad中添加[self updateViewConstraints];進行調用。
2).VFL的結構1:-距離-對象(尺寸)-距離,不能出現-距離-距離的狀況。
3).當出現Unable to simultaneously satisfy constraints時意味着約束之間有衝突,不能知足全部約束。
4).限定一個視圖的約束通常經過與其餘視圖的位置和自身寬高總共4個約束,或者所有與其餘視圖約束,自身不作寬高約束。(4個約束靈活造成一個適配的視圖)
5).約束對象注意,父視圖添加約束,自身寬高約束則是自身當作父視圖來約束。
6).當出現等寬和等高的狀況時,可將同一個方向的兩個視圖約束拆分紅同個方向的2個約束。