屏幕適配
本章節(jié)主要還是說明如何讓應用程序能夠適配在蘋果不同的屏幕和如何讓應用中的內容在不同的屏幕下能夠正常的放置盏筐。
具體說明了:
- 屏幕適配的發(fā)展
- autoresizing的使用
- autolayout的使用
- 代碼實現autolayout
- sizeClass的使用柳爽。
在今天的內容里面將來使用大量的實例來說明不同情況下的適配方式樱报。其中重點是autolayout的使用
- 屏幕適配的發(fā)展
- autoresizing的使用
- autolayout的使用
- sizeClass的使用
了解屏幕適配的發(fā)展史
前言:現在已經不像以前那樣只有一個尺寸疚鲤,現在最少的iPhone開發(fā)需要最少需要適配三個尺寸啸如。因此以前我們可以使用硬坐標去設定各個控件的位置,但是現在的話已經不可以了成翩,我們需要去做適配觅捆,也許你說可以使用兩套UI或兩套以上的UI,但那樣不高效也不符合設計麻敌。iOS有兩大自動布局利器:autoresizing 和 autolayout(autolayout是IOS6以后新增)栅炒。autoresizing是UIView的屬性,一直存在术羔,使用也比較簡單赢赊,但是沒有autolayout那樣強大。如果你的界面比較簡單级历,要求的細節(jié)沒有那么高释移,那么你完全可以使用autoresizing去進行自動布局
iphone3/iphone 3GS:沒有屏幕適配,直接使用frame固定子控件的大小
iphone4 /4s/ipad:iphone屏幕大小一樣鱼喉,但是如果進行ipad開發(fā)秀鞭,就需要考慮屏幕適配
iphone 5/5c/5s:屏幕大小不一樣,需要考慮屏幕適配(使用autoresizing/autolayout實現)
autoresizing的使用
使用autoresizing的前提
需要去除autolayout選項扛禽,因為這兩個屬性沖突锋边。view的autoresizesSubviews屬性為yes時(默認為yes),autoresizing才會生效
-
從XCODE6開始编曼,Storyboard&Xib默認是自動布局豆巨,因此我們需要手動調整,才能使用autoresizing
設置面板說明
使用storyboard實現autoresizing
- 使用屬性面板完成簡單的案例示例
- 體驗六根線的含義
使用代碼實現autoresizing
- UIViewAutoresizing是一個枚舉類型掐场,默認是UIViewAutoresizingNone往扔,也就是不做任何處理
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
- 屬性解釋:
UIViewAutoresizingNone:不會隨父視圖的改變而改變
UIViewAutoresizingFlexibleLeftMargin:自動調整view與父視圖左邊距,以保證右邊距不變
UIViewAutoresizingFlexibleWidth:自動調整view的寬度熊户,保證左邊距和右邊距不變
UIViewAutoresizingFlexibleRightMargin:自動調整view與父視圖右邊距萍膛,以保證左邊距不變
UIViewAutoresizingFlexibleTopMargin:自動調整view與父視圖上邊距,以保證下邊距不變
UIViewAutoresizingFlexibleHeight:自動調整view的高度嚷堡,以保證上邊距和下邊距不變
UIViewAutoresizingFlexibleBottomMargin:自動調整view與父視圖的下邊距蝗罗,以保證上邊距不變
說明一下,如果是經常使用Storyboard/Xib設置autoresizing蝌戒,那么轉變使用代碼設置autoresizing的話串塑,容易出現理解錯誤問題。比如說UIViewAutoresizingFlexibleTopMargin北苟,也許會被誤認為是頂部距離不變桩匪,其實是底部距離不變
autoresizing組合使用:枚舉中的值可以使用|隔開,同時擁有多個值的功能友鼻,可以針對不同的場景作不同的變化:如:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin傻昙。意思是:view的寬度按照父視圖的寬度比例進行縮放,距離父視圖頂部距離不變
-
注意事項:
- 從XCODE6開始彩扔,Storyboard&Xib默認是自動布局屋匕,因此我們需要手動調整,才能使用autoresizing
代碼示例:
- (void)viewDidLoad {
[super viewDidLoad];
//1.添加UIView:以320*480為例
UIView *testView=[[UIView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height-44, self.view.frame.size.width, 44)];
//2.設置UIView的屬性(背景色借杰,frame)
testView.backgroundColor=[UIColor redColor];
//3.添加UIView的autoresizing屬性
//testView.autoresizingMask=UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleTopMargin;
[testView setAutoresizingMask: UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleTopMargin];
//4.添加自定義view到界面
[self.view addSubview:testView];
}
-
autoresizing使用過程中的注意事項
- 一定要先去除use autolayout選項
- 在使用autoreszing的時候是以父容器做為參照進行布局的过吻。
-
autoresizing的局限性
- 它只能描述父子控件之間的布局關系,而不能描述子控件與子控件之間的布局關系
autolayout的使用
-
使用場合:
- 現在Apple發(fā)布的各個產品上市之后蔗衡,設備的屏幕分辨率也有了很大的變化纤虽,iPhone4/4S是3.5寸,iPhone5是4.0寸绞惦,ipad2/new ipad/ipad4是9.7寸的逼纸,ipad mini是7.0的,分辨率也各不相同济蝉,使用傳統(tǒng)frame布局的工作量必將越來越大
- 可以為一個ViewController做出幾個不同的尺寸的View來杰刽,但是這樣會大大的影響到開發(fā)的速度
- autolayout:一種對不同屏幕尺寸有更好兼容的自動布局機制
- 好處:
1菠发、你基本上可以不用考慮屏幕不同分辨率的問題,你終于可以不用在viewDidLoad方法里判斷不同分辨率下贺嫂,不同控件應該放在哪里滓鸠,或者針對不同分辨率寫不同的storyboard和xib
2、你可以拋棄那些根據不同文字來計算tableViewCell第喳、UILabel高度的代碼了糜俗,因為autolayout會幫你自動計算好
3、如果你的布局在橫屏豎屏下變化不是特別大曲饱,你不用再為橫著豎著寫兩套代碼或者寫兩個storyboard/xib了 - 所以:當你的頁面不會變更整體布局和設計悠抹,只有在不同屏幕尺寸、不同文字和內容下有適應性的變化扩淀,那這種情況使用autolayout就再適宜不過了
-
設置autolayout的屬性面板說明
-
pin面板和align面板:
-
resolve面板:
-
resizing behevior面板:
-
-
使用autolayout不再需要設置子控件的frame
- 通過使用 父子控件之間的約束 或者 子控件與子控件之間的約束進行frame的設置楔敌。
-
添加約束示例:
-
使用autolayout過程中的注意事項:約束缺失和約束沖突
- 紅色:說明必須的四個約束有缺失,添加缺失的約束就可以
- 黃色:說明重復添加了約束驻谆,可以選擇刪除其中重復的約束
-
代碼實現autolayout
- 使用NSLayoutConstraint這個類為子控件添加約束
- 添加約束的統(tǒng)一語法規(guī)律:
item1.attribute = multiplier ? item2.attribute + constant梁丘,
對應的添加約束的方法:
[NSLayoutConstraint constraintWithItem:<#(需要添加約束的子控件對象)#> attribute:<#(為子控件的哪一個屬性添加約束)#> relatedBy:<#(如何進行約束(如大于贝淤,等于...))#> toItem:<#(參照的控件對象)#> attribute:<#(所參照控件的哪一個屬性)#> multiplier:<#(倍數)#> constant:<#(增加的常量值)#>]范咨;
-
添加約束的規(guī)則:
- 對于兩個同層級view之間的約束關系,添加到它們的父view上
- 對于兩個不同層級view之間的約束關系酝惧,添加到他們最近的共同父view上
- 對于有層次關系的兩個view之間的約束關系区端,添加到層次較高的父view上
代碼添加約束示例:
- (void)viewDidLoad {
[super viewDidLoad];
UIView *redView=[[UIView alloc] init];
redView.backgroundColor=[UIColor redColor];
[self.view addSubview:redView];
//添加子控件
UIView *blueView=[[UIView alloc] init];
blueView.backgroundColor=[UIColor blueColor];
[redView addSubview:blueView];
//1.一定要禁用autoresizing
redView.translatesAutoresizingMaskIntoConstraints=NO;
blueView.translatesAutoresizingMaskIntoConstraints=NO;
//2.創(chuàng)建約束
//添加高度約束
NSLayoutConstraint *constriantH=[NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0 constant:40];
//設置頂部間距約束
NSLayoutConstraint *constriantT=[NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:30];
//設置左邊間距約束
NSLayoutConstraint *constriantL=[NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0];
//設置右邊間距約束
NSLayoutConstraint *constriantR=[NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:0];
//添加藍色view的約束
NSLayoutConstraint *blueX=[NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:redView attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
NSLayoutConstraint *blueH=[NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:redView attribute:NSLayoutAttributeHeight multiplier:1 constant:0];
NSLayoutConstraint *blueR=[NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:redView attribute:NSLayoutAttributeRight multiplier:1 constant:0];
NSLayoutConstraint *blueT=[NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:redView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:30];
//添加約束到控件值漫,注意添加的規(guī)則
[redView addConstraint:constriantH];
[self.view addConstraint:constriantT];
[self.view addConstraint:constriantL];
[self.view addConstraint:constriantR];
[self.view addConstraint:blueX];
[self.view addConstraint:blueH];
[self.view addConstraint:blueR];
[self.view addConstraint:blueT];
}
了解VFL語言的簡單說明和使用--不需要掌握
-
什么是VFL語言:
- 全稱是Visual Format Language,翻譯過來是“可視化格式語言”织盼,是蘋果公司為了簡化Autolayout的編碼而推出的抽象語言
-
VFL語言的語法
-
例如杨何;H:|-間距-[view1對象名]-(>=20)-[view2對象名]
- H:表示水平方向,V表示垂直方向沥邻,不寫H/V就表示橫向
- "|"是用來確定view上危虱、下、左唐全、右關系的埃跷,如果當前是H,那么就代表水平方向的參照控件的左邊或者右邊邮利,如果是V就代表參照控件的頂邊或者底邊
- 如果是H弥雹,這個表達式就可以從左到右描述當前view及與參照view的關系,如果是V延届,類似剪勿。
- 方括號表示view,圓括號表示尺寸數值方庭。支持大小等于厕吉〗垂蹋或者另一個view 如:H:|-[view1(view2)],v1的寬度等于v2
- 優(yōu)先級用@表示
- 上面這句VFL代碼的意思就是:view1離父控件左邊有一個間距头朱,之后有一個view2控件运悲,view2控件與view1控件有一個>=20的間距。
VFL語言的使用
UIView *redView=[[UIView alloc] init];
redView.backgroundColor=[UIColor redColor];
[self.view addSubview:redView];
//添加子控件
UIView *blueView=[[UIView alloc] init];
blueView.backgroundColor=[UIColor blueColor];
[self.view addSubview:blueView];
//1.一定要禁用autoresizing
redView.translatesAutoresizingMaskIntoConstraints=NO;
blueView.translatesAutoresizingMaskIntoConstraints=NO;
//2.創(chuàng)建約束
//2.1創(chuàng)建redView的頂部間距約束
NSString *redT=@"V:|-paddingT-[redView]-padding-[blueView]";
NSDictionary *redTmetrics=@{@"paddingT":@40,@"padding":@60};
NSDictionary *redTviews=@{@"redView":redView,@"blueView":blueView};
NSArray *redConT=[NSLayoutConstraint constraintsWithVisualFormat:redT options:0 metrics:redTmetrics views:redTviews];
//2.2創(chuàng)建redView的左右間距約束
NSString *redLR=@"H:|-paddingL-[redView]-paddingR-|";
NSDictionary *redLRmetrics=@{@"paddingL":@10,@"paddingR":@10};
//NSDictionary *redLRviews=@{@"redView":redView};
NSArray *redConLR=[NSLayoutConstraint constraintsWithVisualFormat:redLR options:0 metrics:redLRmetrics views:redTviews];
//2.3創(chuàng)建redView的高度約束
NSString *redH=@"V:[redView(44)]";
NSArray *redConH=[NSLayoutConstraint constraintsWithVisualFormat:redH options:0 metrics:nil views:redTviews];
//添加約束
[self.view addConstraints:redConT];
[self.view addConstraints:redConLR];
[redView addConstraints:redConH];
第三方框架實現autolayout
使用前面兩種方式都不是很方便髓窜,在公司開發(fā)項目的時候一般會使用成熟的第三方框架
-
我們常用的框架masonry
- 將框架文件件添加到項目
- 導入頭文件
- 代碼示例:
- (void)viewDidLoad {
[super viewDidLoad];
//1.創(chuàng)建紅色view
UIView *redView=[[UIView alloc] init];
redView.backgroundColor=[UIColor redColor];
[self.view addSubview:redView];
//2.創(chuàng)建藍色view
UIView *blueView=[[UIView alloc] init];
blueView.backgroundColor=[UIColor blueColor];
[self.view addSubview:blueView];
//3.為紅色view添加約束
[redView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(30);//離頂部的距離
make.left.mas_equalTo(10);//離左邊的距離
make.right.mas_equalTo(-10);//離右邊的距離
make.height.mas_equalTo(44);//高度
}];
//4.為藍色view添加約束
[blueView mas_makeConstraints:^(MASConstraintMaker *make) {
//藍色塊離紅色塊的底部有30的距離
make.top.mas_equalTo(redView.mas_bottom).offset(30);//離頂部的距離
//藍色塊的左邊與紅色塊的水平中心對齊
make.left.mas_equalTo(redView.mas_centerX);//離左邊的距離
make.right.mas_equalTo(-10);//離右邊的距離
make.height.mas_equalTo(redView);//高度
}];
}
- 使用autolayout重新布局“微博"小項目扇苞。
不需要再使用Frame模型
-
使用動態(tài)單元格進行布局欺殿,設置約束
進行約束的連線寄纵,根據配圖判斷是否需要修改約束
if(self.statu.picture)
{
self.pictureView.hidden=NO;
self.pictureView.image=[UIImage imageNamed:self.statu.picture];
self.cellHeight.constant=100;
}
else
{
self.pictureView.hidden=YES;
self.cellHeight.constant=0;
}
- 讓tableView高度自動變化
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.rowHeight=UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight=44;
}
使用autolayout過程中的注意事項及細節(jié)。
- 一定要禁用autoresizing
- 一定要將約束添加完整
autolayout和autoresizing的優(yōu)勢:
- AutoLayout可以指定任意兩個view的相對位置脖苏,而不需要像Autoresizing Mask那樣需要兩個view有直接的父子關系程拭。
- AutoLayout不必須指定相等關系的約束,它可以指定非相等約束(大于或者小于等)棍潘;而Autoresizing Mask所能做的布局只能是相等條件的恃鞋。
- AutoLayout可以指定約束的優(yōu)先級,計算frame時將優(yōu)先按照滿足優(yōu)先級高的條件進行計算亦歉。
- Autoresizing Mask是AutoLayout的子集恤浪,任何可以用Autoresizing Mask完成的工作都可以用AutoLayout完成。AutoLayout還具備一些Autoresizing Mask不具備的優(yōu)良特性肴楷,以幫助我們更方便地構建界面水由。
sizeClass的使用
sizeClass的由來:
iOS8之前,公司在開發(fā)項目時,先做的iPhone版,然后要求開發(fā)iPad版本,其實內容是完全一樣的,只是UI變化了,但是我們就需要建立2個工程來分別對應實現.iOS8推出的Size Class,可以讓我們在一個工程的storyboard中進行所有尺寸屏幕的適配,不僅是iPhone 4s-5/5s-6-6 Plus,還包括iPad界面.它引入了一種新的概念,拋棄傳統(tǒng)意義上我們適配時所謂的具體寬高尺寸,把屏幕的寬和高分別分成兩種情況:Compact-緊湊, Regular-正常(Any-任意,其實就是這2種的組合,所以我沒分成3種情況)sizeClass能夠實現那些效果:解決橫屏適配和iPhone iPad共享一個界面
any compact regular的含義
iPhone4S,iPhone5/5s,iPhone6
豎屏:(w:Compact h:Regular)
橫屏:(w:Compact h:Compact)
iPhone6 Plus
豎屏:(w:Compact h:Regular)
橫屏:(w:Regular h:Compact)
iPad
豎屏:(w:Regular h:Regular)
橫屏:(w:Regular h:Regular)具體使用sizeClass
使用sizeClass過程中的注意事項及細節(jié)
*從 iOS8開始才支持 size classes
*size classes本質就是對所有的屏幕進行了分類, 我們可以為不同類型的屏幕設置不同的約束
*僅僅是對屏幕進行了分類, 真正排布UI元素還得使用autolayout
*不再有橫豎屏的概念, 只有屏幕尺寸的概念
*不再有具體尺寸的概念, 只有抽象尺寸的概念
*把寬度和高度各分為3種情況
1> any(任意, 表示既可以是compact, 也可以是regular), 一般用 * 表示
2> compact(緊湊, 小), 一般用 - 表示
3> regular(正常, 大),
*注意:
一般不要在 wAny 和 hAny下設置約束, 否則當在 wAny 和 hAny下設置約束后, 在其他尺寸的屏幕再設置約束會產生沖突。因為約束會被繼承下來赛蔫。約束的繼承關系(*符號就表示+ 或者 -):
* * : 其它8種情況都會繼承
* - : 會被- - \ + -繼承
+ * : 會被+ - \ + +繼承