生活随笔
收集整理的這篇文章主要介紹了
                                
iOS8开发~UI布局(三)深入理解autolayout
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
 
                                
                            
                            
                            一、概要
 
  通過對iOS8界面布局的學習和總結,發現autolayout才是主角,autolayout是iOS6引入的新特性,當時還粗淺的學習了下,可是沒有真正應用到項目中。隨著iOS設備尺寸逐漸碎片化,純粹的hard code方式UI布局將會走向死角,而autoresizing方式也有其局限性,所以無論如何autolayout都將成為UI布局的重要方式。
  前兩篇以發燒友心態對iOS8界面布局的主要元素size class和autolayout進行了探索,發現要完全掌握autolayout需要大量的時間去實踐總結。所以深入思考autolayout是很有必要的。你可能有和我同樣的疑問,如下:
  1、以后一律使用autolayout嗎?除了在storyboard中使用autolayout,代碼方式autolayout如何使用?
  2、好像忽略了一個重要問題,就是view動畫在autolayout如何實現?
  3、autolayout有沒有局限性和解決不了的問題?兼容性怎么樣?效率怎么樣?
  4、……
  二、研究開始
  1、直接說以后都應該使用storyboard+autolayout感覺是不負責的說法,讀了好多網絡的帖子,最后總結如下情況使用autolayout會有幫助:
  a 當需要展示的內容很多并且尺寸不固定;
  b 程序需支持屏幕旋轉(主要是iPad程序,iPhone程序橫屏的場景有點非主流);
  c 程序通用于iPhone和iPad;
 
  
 
  但storyboard中使用autolayout有利有弊,好處當然是可視化,實現簡單功能很節省時間,但也有弊端,例如不小心移動一個控件就會讓弄亂那些約束。拋開storyboard而使用autolayout,就需要代碼定義約束了,而且代碼量也不是很大。當app中一些view的出現時根據網絡數據來決定的時候,代碼方式可能更合適。
  
  先看一個簡單的Demo:
  例子1:新建一個Single View Application template項目Demo4,在rootView上添加一個綠顏色的view,使新添加的view四個邊距離superView四邊20點寬
  效果如圖:
  
 
  使用storyboard來實現這個效果很簡單,選中綠色view,然后添加4個相對于superview的邊界約束,約束的數值設置為20,然后Update Frame就可以了,因為不區分iOS設備,所以size class可以設置為默認的wAny hAny。Demo下載
  接下來使用代碼來實現UI布局,目前有3種方法可以使用:(1)最基本的約束實現方式;(2)特殊格式化語言的約束實現方式;(3)第三方UIView-AutoLayout
  (1)最基本的約束實現方式
 
  
    [objc]?view plaincopy       
 <span?style="font-size:12px;">-?(void)viewDidLoad?{?? ????[super?viewDidLoad];?? ?????? ????self.view.translatesAutoresizingMaskIntoConstraints?=NO;?? ?????? ????UIView?*newView?=?[UIView?new];?? ????newView.backgroundColor?=?[UIColor?greenColor];?? ????[self.view?addSubview:newView];?? ?????? ????newView.translatesAutoresizingMaskIntoConstraints?=NO;?? ?????? ????NSLayoutConstraint?*constraint?=?nil;?? ?????? ????constraint?=?[NSLayoutConstraint?constraintWithItem:newView?? ??????????????????????????????????????????????attribute:NSLayoutAttributeLeading?? ??????????????????????????????????????????????relatedBy:NSLayoutRelationEqual?? ?????????????????????????????????????????????????toItem:self.view?? ??????????????????????????????????????????????attribute:NSLayoutAttributeLeading?? ?????????????????????????????????????????????multiplier:1.0f?? ???????????????????????????????????????????????constant:20];?? ????[self.view?addConstraint:constraint];?? ?????? ????constraint?=?[NSLayoutConstraint?constraintWithItem:newView?? ??????????????????????????????????????????????attribute:NSLayoutAttributeTrailing?? ??????????????????????????????????????????????relatedBy:NSLayoutRelationEqual?? ?????????????????????????????????????????????????toItem:self.view?? ??????????????????????????????????????????????attribute:NSLayoutAttributeTrailing?? ?????????????????????????????????????????????multiplier:1.0f?? ???????????????????????????????????????????????constant:-20];?? ????[self.view?addConstraint:constraint];?? ?????? ????constraint?=?[NSLayoutConstraint?constraintWithItem:newView?? ??????????????????????????????????????????????attribute:NSLayoutAttributeTop?? ??????????????????????????????????????????????relatedBy:NSLayoutRelationEqual?? ?????????????????????????????????????????????????toItem:self.view?? ??????????????????????????????????????????????attribute:NSLayoutAttributeTop?? ?????????????????????????????????????????????multiplier:1.0f?? ???????????????????????????????????????????????constant:20];?? ????[self.view?addConstraint:constraint];?? ?????? ????constraint?=?[NSLayoutConstraint?constraintWithItem:newView?? ??????????????????????????????????????????????attribute:NSLayoutAttributeBottom?? ??????????????????????????????????????????????relatedBy:NSLayoutRelationEqual?? ?????????????????????????????????????????????????toItem:self.view?? ??????????????????????????????????????????????attribute:NSLayoutAttributeBottom?? ?????????????????????????????????????????????multiplier:1.0f?? ???????????????????????????????????????????????constant:-20];?? ????[self.view?addConstraint:constraint];?? ?????? }</span>??  
 (2)特殊格式化語言的約束實現方式  
  
    [objc]?view plaincopy       
 <span?style="font-size:12px;">-?(void)viewDidLoad?{?? ????[super?viewDidLoad];?? ????self.view.translatesAutoresizingMaskIntoConstraints?=NO;?? ?????? ????UIView?*newView?=?[UIView?new];?? ????newView.backgroundColor?=?[UIColor?greenColor];?? ????[self.view?addSubview:newView];?? ????newView.translatesAutoresizingMaskIntoConstraints?=NO;?? ?????? ????NSMutableArray?*constraintArray?=?[NSMutableArray?array];?? ?????? ????[constraintArray?addObjectsFromArray:[NSLayoutConstraint?constraintsWithVisualFormat:@"H:|-20-[newView]-20-|"?? ?????????????????????????????????????????????????????????????????????????????????options:0?? ?????????????????????????????????????????????????????????????????????????????????metrics:nil?? ???????????????????????????????????????????????????????????????????????????????????views:NSDictionaryOfVariableBindings(newView,?self.view)]];?? ????[constraintArray?addObjectsFromArray:[NSLayoutConstraint?constraintsWithVisualFormat:@"V:|-20-[newView]-20-|"?? ?????????????????????????????????????????????????????????????????????????????????options:0?? ?????????????????????????????????????????????????????????????????????????????????metrics:nil?? ???????????????????????????????????????????????????????????????????????????????????views:NSDictionaryOfVariableBindings(newView,?self.view)]];?? ????[self.view?addConstraints:constraintArray];?? }</span>??  
 (3)第三方UIView-AutoLayout
   
  
    [objc]?view plaincopy       
 <span?style="font-size:12px;">-?(void)viewDidLoad?{?? ????[super?viewDidLoad];?? ????self.view.translatesAutoresizingMaskIntoConstraints?=NO;?? ?????? ????UIView?*newView?=?[UIView?new];?? ????newView.backgroundColor?=?[UIColor?greenColor];?? ????[self.view?addSubview:newView];?? ????newView.translatesAutoresizingMaskIntoConstraints?=NO;?? ?????? ????[newView?autoPinEdgeToSuperviewEdge:ALEdgeLeading?withInset:20.0f];?? ????[newView?autoPinEdgeToSuperviewEdge:ALEdgeTrailing?withInset:20.0f];?? ????[newView?autoPinEdgeToSuperviewEdge:ALEdgeTop?withInset:20.0f];?? ????[newView?autoPinEdgeToSuperviewEdge:ALEdgeBottom?withInset:20.0f];?? }</span>??  
 以上3種方式都實現了我們想要的效果,看來代碼實現autolayout也不是那么復雜!  
  
 
  例子2:通過上邊例子我們實現一個簡單的UI布局,下面來一個稍微復雜點的,把上一篇中提到3個view布局的那個例子用代碼布局實現一下,但難度有所增加,當size class切換的時候,頁面布局發生相應的改變,效果如圖:
  ? ? ? ? ? ??
 
  首先初始化3個View:
  
    [objc]?view plaincopy       
 <span?style="font-size:12px;">-?(UIView?*)?alView?{?? ????UIView?*newView?=?[UIView?new];?? ????newView.translatesAutoresizingMaskIntoConstraints?=NO;?? ?????? ????return?newView;?? }?? UIView?*greenView?=?[self?alView];?? greenView.backgroundColor?=?[UIColor?greenColor];?? [self.view?addSubview:greenView];?? UIView?*yellowView?=?[self?alView];?? yellowView.backgroundColor?=?[UIColor?yellowColor];?? [self.view?addSubview:yellowView];?? UIView?*blueView?=?[self?alView];?? blueView.backgroundColor?=?[UIColor?blueColor];?? [self.view?addSubview:blueView];</span>??  
   
  接下來適配豎屏的約束:
  
    [objc]?view plaincopy       
 <span?style="font-size:12px;">-?(NSMutableArray?*)?portraitConstraints:(UIView?*)greenView?:(UIView?*)yellowView?:(UIView?*)blueView?? {?? ????NSMutableArray?*constraintArray?=?[NSMutableArray?array];?? ?????? ????[constraintArray?addObjectsFromArray:[NSLayoutConstraint?? ??????????????????????????????????????????constraintsWithVisualFormat:@"H:|-20-[greenView]-20-[yellowView(==greenView)]-20-|"?options:0?metrics:nil?? ??????????????????????????????????????????views:NSDictionaryOfVariableBindings(greenView,?yellowView)]];?? ????[constraintArray?addObjectsFromArray:[NSLayoutConstraint?? ??????????????????????????????????????????constraintsWithVisualFormat:@"V:|-20-[greenView]-20-[blueView(==greenView)]-20-|"?options:0?metrics:nil?? ??????????????????????????????????????????views:NSDictionaryOfVariableBindings(greenView,?blueView)]];?? ?????? ????[constraintArray?addObjectsFromArray:[NSLayoutConstraint?? ??????????????????????????????????????????constraintsWithVisualFormat:@"V:|-20-[yellowView]-20-[blueView(==yellowView)]-20-|"?options:0?metrics:nil?? ??????????????????????????????????????????views:NSDictionaryOfVariableBindings(yellowView,?blueView)]];?? ?????? ????[constraintArray?addObjectsFromArray:[NSLayoutConstraint?? ??????????????????????????????????????????constraintsWithVisualFormat:@"H:|-20-[blueView]-20-|"?options:0?metrics:nil?? ??????????????????????????????????????????views:NSDictionaryOfVariableBindings(blueView)]];?? ?????? ????return?constraintArray;?? }</span>??  
 然后橫屏的約束:  
  
    [objc]?view plaincopy       
 <span?style="font-size:12px;">-?(NSMutableArray?*)?landscapeConstraints:(UIView?*)greenView?:(UIView?*)yellowView?:(UIView?*)blueView?? {?? ????NSMutableArray?*constraintArray?=?[NSMutableArray?array];?? ?????? ????[constraintArray?addObjectsFromArray:[NSLayoutConstraint?? ??????????????????????????????????????????constraintsWithVisualFormat:@"H:|-20-[greenView]-20-[yellowView(==greenView)]-20-|"?options:0?metrics:nil?? ??????????????????????????????????????????views:NSDictionaryOfVariableBindings(greenView,?yellowView)]];?? ?????? ????[constraintArray?addObjectsFromArray:[NSLayoutConstraint?? ??????????????????????????????????????????constraintsWithVisualFormat:@"V:|-20-[blueView]-20-[greenView(==blueView)]-20-|"?options:0?metrics:nil?? ??????????????????????????????????????????views:NSDictionaryOfVariableBindings(greenView,?blueView)]];?? ?????? ????[constraintArray?addObjectsFromArray:[NSLayoutConstraint?? ??????????????????????????????????????????constraintsWithVisualFormat:@"V:|-20-[blueView]-20-[yellowView(==blueView)]-20-|"?options:0?metrics:nil?? ??????????????????????????????????????????views:NSDictionaryOfVariableBindings(yellowView,?blueView)]];?? ?????? ????[constraintArray?addObjectsFromArray:[NSLayoutConstraint?? ??????????????????????????????????????????constraintsWithVisualFormat:@"H:|-20-[blueView]-20-|"?options:0?metrics:nil?? ??????????????????????????????????????????views:NSDictionaryOfVariableBindings(blueView)]];?? ?????? ????return?constraintArray;?? }</span>??  
 最后還要處理屏幕旋轉:  
  
    [objc]?view plaincopy       
 <span?style="font-size:12px;">-?(void)willTransitionToTraitCollection:(UITraitCollection?*)newCollection?? ??????????????withTransitionCoordinator:(id?<UIViewControllerTransitionCoordinator>)coordinator?? {?? ????[super?willTransitionToTraitCollection:newCollection?withTransitionCoordinator:coordinator];?? ?????? ????[coordinator?animateAlongsideTransition:^(id?<UIViewControllerTransitionCoordinatorContext>?context)?{?? ????????if?(newCollection.verticalSizeClass?==?UIUserInterfaceSizeClassCompact)?{?? ????????????NSLog(@"%s----%d",?__FUNCTION__,?__LINE__);?? ????????????[self.view?removeConstraints:self.view.constraints];?? ????????????[self.view?addConstraints:[self?landscapeConstraints:self.greenView_?:self.yellowView_?:self.blueView_]];?? ????????}?else?{?? ????????????NSLog(@"%s----%d",?__FUNCTION__,?__LINE__);?? ????????????[self.view?removeConstraints:self.view.constraints];?? ????????????[self.view?addConstraints:[self?portraitConstraints:self.greenView_?:self.yellowView_?:self.blueView_]];?? ????????}?? ????????[self.view?setNeedsLayout];?? ????}?completion:nil];?? }</span>??  
 這樣就實現了我們預期的效果,總結下來,auotlayout就是給view添加足夠的約束,讓view系統可以根據約束來計算出一個view的frame。動手練習一下吧!  
  
 
  2、view動畫在autolayout實現
 
  當布局發生改變時,相當于對子view進行重新布局,而子view重新布局調用?layoutIfNeeded,所以動畫可以這樣實現:
  
    [objc]?view plaincopy       
 <span?style="font-size:12px;">-?(void)animateConstraints?? {?? ????[UIView?animateWithDuration:0.5?animations:^{?? ????????[self.view?layoutIfNeeded];?? ????}];?? }</span>??  
 Github上已經有Demo了!  
  
 
  3、autolayout有沒有局限性和解決不了的問題?兼容性怎么樣?效率怎么樣?
 
  autolayout對view transforms支持的不好,這里有帖子詳細描述了這個問題。
 
  至于兼容性,只從iOS6就已經提出了autolayout的概念,現在iOS5系統不是很多了,甚至iOS6系統都已經升級為iOS7,未來一段時間大部分用戶應該是使用iOS7和iOS8系統,所以兼容性問題不會太大,但size class是iOS8才有的概念,所以還有有一定的適配工作量。
  效率話題這里有提到,有時間再細研究。
  
 
  結束語:時間和體力總是有限的,標題是autolayout詳解,可想達到詳解還需要更多的時間去實踐和總結,還有一些細節沒有體現出來:
  例如:
  
    [objc]?view plaincopy       
 <span?style="font-size:12px;">[NSLayoutConstraint?constraintsWithVisualFormat:@"H:|-20-[newView]-20-|"options:0?metrics:nil?views:NSDictionaryOfVariableBindings(newView,?self.view)]</span>??   1、這其中各個參數的含義,另外約束還有個優先級的概念
 
  2、@"H:|-20-[newView]-20-|" 這種可視化布局字符串的含義等等,有空再補充了!
  本篇內容所有Demo
 歡迎指出錯誤,不勝感激。
                            總結
                            
                                以上是生活随笔為你收集整理的iOS8开发~UI布局(三)深入理解autolayout的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                            
                                如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。