AutoLayout全解
AutoLayout簡介
Autolayout是一種全新的布局技術,專門用來布局UI界面的,用來取代Frame布局在遇見屏幕尺寸多重多樣的問題。Autolayout自iOS 6開始引入,但是由于Xcode 4的不給力,當時并沒有得到大規模推廣。在iOS 7(Xcode5)開始,Autolayout的開發效率得到很大的提升,蘋果官方也推薦開發者盡量使用Autolayout來布局UI界面,減少純代碼的方式。
那么AutoLayout怎么使用呢?
VFL
VFL(Virsual Format Language)是一種虛擬的格式化語言,主要用來創建AutoLayout的約束字符串。
示例,如:V: |-(0)-Label1-(0)-Label2-(0)-| 方向:從左到右,從上到下
V:表示方向為垂直方向,也就是豎向;H為橫向。
|:豎線表示為邊界(當前所在View的邊界),這里緊鄰方向表示符V,方向是從上到下,因此表示上面界。
0:NSNumber 0 表示約束值為0。這里是Label1距離上邊界的約束為0。
Label1:表示對象Label1。
0:表示Label1和Label2的約束為0.
Label2:表示對象Label2。
0:表示Label2和下邊界的約束為0.
|:表示下邊界。
關于[VFL官網]詳細知識,請查看官方的介紹
AutoLayout IB使用方式
為了讓布局能夠在不同屏幕的size上都能夠表現正常,我們需要對其增加“約束”。然后,在不同屏幕尺寸下view就能夠按照約束來局。
添加如下約束:
案例1
設置某個View距離父View上下左右間距全部為20。
案例2
某個View距離父View的左側20,上20,寬高均為100。
案例3
某個View距離在父View的左側20 案例2中白色View 上20 寬高和Demo2中的寬高一樣。
然后,點擊某個約束。
對其處理
屬性說明:
- Leading Edges:左對齊
- Trailing Edges:右對齊
- Top Edges:上對齊
- Bottom Edges:下對齊
- Horizontal Centers:水平中心對齊
- Vertical Centers:豎向中心對齊
- Baselines:基線對齊
- Horizontal Center in Container:對齊容器中的水平中心
- Vertical Center in Container:對齊容器中的豎向中心
案例4
某個View距離在父View的右側20 案例3中白色View上20 寬高和案例3中的寬高一樣 并且對齊。
案例5
某個label和另外一個label基線對齊。
像label 默認是有寬度的 寬度就是字體自適應的。這樣我們就可以不給UIlabel 高度 把Label的NumberOfline = 0就可以自適應高度了。
Tip
1,有時候約束太多的時候 我們可以給某個View起個假名字以起到唯一標識的作用。
2,View總是選不中怎么辦?按 ctrl + shift + 單擊。
3,當ScrollView過長無法編輯怎么辦?將控制器改為Freedom 修改ContentView的高度約束 這樣ScrollView 就可以滾動了。
UItableViewCell高度計算
為了方便說明,本部分知識主要從以下幾個方面講解。
- AutoLayout with UILabel in UITableViewCell
- AutoLayout with UITextView in UITableViewCell
- Manual Layout with UILabel in UITableViewCell
- Manual Layout with UITextView in UITableViewCell
- 隨UITextView高度動態改變Cell高度
AutoLayout with UILabel
創建一個空的xib,命名為C1.xib, 然后拖入一個UITableViewCell控件。接著創建一個UITableViewCell的子類,命名為C1類。然后在C1.xib中,將與C1類進行關聯。只需要在Class那里寫入關聯的類名C1即可。
還有由于UITableViewCell需要重用功能,所以我們還需要設置一個重用標識。
下面是使用autoLayout的布局。
接著我們在UITableView中來使用我們自定義的UITableViewCell C1。首先我們創建一個UITableViewController的子類T1ViewController, 接著在Main.storyboard中拖入一個UITableViewController,并關聯T1ViewController。
Auto Layout with UITextView
同樣參考上面我們創建一個C2.xib, UITableViewCell的子類C2,并關聯C2.xib與C2類。并在C2.xib中對其布局,同樣使用了auto layout. 布局如下圖:
創始UITableViewController的了類T2ViewController,在Main.storyboard中拖入UITableViewController,并關聯他們。接著代碼中注冊C2.xib到UITableView。
如下面是計算UITableView高度的代碼:
在這兒我們是通過sizeThatFits:計算的UITextView的高度,然后加上systemLayoutSizeFittingSize:返回的高度。為什么要這樣呢? 因為UITextView內容的高度不會影響systemLayoutSizeFittingSize計算。
下面是UITextView的實例:
此圖中距頂的約束是10, 距底的約束8, 距左邊約束是87,距右邊的約束是13, 那么systemLayoutSizeFittingSize:返回的CGSize為height等于19, size等于100. 它UITextView的frame是不影響systemLayoutSizeFittingSize:的計算。所以,我們需要加上textViewSize.height。
Manual Layout with UILabel
按照前面介紹的,我們需要創建C3.xib, C3類, T3ViewController類,Main.storyboard中拖入UITableViewController,并分別建立關聯。 為了簡單,C3.xib中我就不加padding之類的了,如圖:
然后添加如下的計算代碼:
這里,用到了一個NSString的Cagetory方法,代碼如下:
- (CGSize)calculateSize:(CGSize)size font:(UIFont *)font {CGSize expectedLabelSize = CGSizeZero;if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;NSDictionary *attributes = @{NSFontAttributeName:font, NSParagraphStyleAttributeName:paragraphStyle.copy};expectedLabelSize = [self boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil].size;}else {expectedLabelSize = [self sizeWithFont:fontconstrainedToSize:sizelineBreakMode:NSLineBreakByWordWrapping];}return CGSizeMake(ceil(expectedLabelSize.width), ceil(expectedLabelSize.height)); }運行效果如下:
Manual Layout with UITextView
按照前面介紹的,我們需要創建C4.xib, C4類, T4ViewController類,Main.storyboard中拖入UITableViewController,并分別建立關聯。 為了簡單,C4.xib中我就不加padding之類的了,如圖:
相關代碼如下:
隨UITextView高度改變Cell高度
當UITextView內容改變的時候,計算自身高度,然后通知UITableView更新,這樣就會觸發UITableViewCell高度重新計算,從而改變Cell的高度。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {C5 *cell = [self.tableView dequeueReusableCellWithIdentifier:@"C5"];cell.t.text = @"123";cell.t.delegate = self;return cell; }#pragma mark - UITableViewDelegate - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {C5 *cell = (C5 *)self.prototypeCell;cell.t.text = self.updatedStr;CGSize s = [cell.t sizeThatFits:CGSizeMake(cell.t.frame.size.width, FLT_MAX)];CGFloat defaultHeight = cell.contentView.frame.size.height;CGFloat height = s.height > defaultHeight ? s.height : defaultHeight;return 1 + height; }#pragma mark - UITextViewDelegate - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {if ([text isEqualToString:@"\n"]) {NSLog(@"h=%f", textView.contentSize.height);}return YES; }- (void)textViewDidChange:(UITextView *)textView {self.updatedStr = textView.text;[self.tableView beginUpdates];[self.tableView endUpdates]; }關于UITableViewCell使用自動布局的優化可以查看下面的介紹:
優化UITableViewCell高度計算。
StackView
UIStackView是iOS9新引入的控件,它支持垂直和水平排列多個子視圖(SubView)。例如:水平放置三個按鈕,等寬,并且按鈕間的間隙為10,如果自己實現會比較麻煩,而使用UIStackView則很容易實現。UIStackView目前只支持iOS9+版本,如果要在iOS 7版本上使用UIStackView,可以使用下面兩個第三方庫:OAStackView和TZStackView。其中:
- OAStackView,基于OC的StackView庫,支持iOS7+以上的系統,同時支持代碼和IB視圖。
- TZStackView,基于Swift的StackView庫,同樣支持iOS7+以上的系統,但是不支持storyboard。
OAStackView實現子視圖等分
案例1
例如,下面的例子是使用OAStackView實現視圖等分的例子。
相關代碼如下:
上面的例子實現了兩個按鈕的垂直排列。如果想要水平排列,修改stackView.axis值為UILayoutConstraintAxisHorizontal即可。需要注意,因為不是用IB創建的View,所以要設定View的translatesAutoresizingMaskIntoConstraints屬性為NO,否則排列屬性不生效。當非IB創建時,屬性默認為YES;當IB創建View時,屬性默認為NO。
案例2
在水平方向上放4張圖片,圖片等分。
1,首先在頁面上拖拽1個imageView,將它的寬高都設置成50。
2,然后再添加三個imageView,將界面上的四個ImageView設置等寬等高。
3,然后再將他們加入到Stack View中,設置Stack View 的distribution屬性為 Equal Spacing(等間距)。
4,最后,設置Stack View 的位置
StackView屬性
在理解StackView時,有幾個屬性需要理解:
Axis: 這個屬性是改變UIStackView中的排布方式的屬性,其中有水平排布與垂直排布
- Alignment:這個屬性是其中子視圖的位置擺布方式默認是填充擺布
- Fill:子視圖填充他所在的位置(默認)
- Leading:子視圖頭部對齊
- Center:子視圖居中對齊
- Trailing:子視圖尾部對齊
- Distribution:子視圖的大小
- Fill:子視圖填充整個UIStackView
- Fill Equally:子視圖填充空白區域并等分
- Fill Proportionally:按照目前相對位置進行填充
- Equal Spacing:等間距
- Spacing設置子視圖之間的間距大小
- Baseline Relative:如果設置子視圖間距的大小為基線到下一個視圖的頭部
總結
以上是生活随笔為你收集整理的AutoLayout全解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 比世界纪录快3倍 阿里云377秒完成10
- 下一篇: 为女儿取名“王者荣耀”可想过代价?