在Autolayout小結(一)中介紹了在Autolayout學習中一些基本的注意點,本文會針對一些佈局上常見的問題進行分析。ide
如何自動適應cell的高度佈局
如何在ScrollView中使用Autolayout學習
使用Autolayout作動畫測試
Autolayout在IOS6上的坑動畫
在IOS的佈局中,計算和適應cell的高度是個經典的問題, 在frame時代,咱們都知道用sizeWithFont:
先計算出文字的高度,而後經過計算得出cell的高度,而後賦予heightForRow:
。ui
那在Autolayout時代如何計算cell的高度呢?由於sizeWithFont:方法已經不太實用了。其實Autolayout不但更簡單,還能夠不用寫過多的計算代碼達到自適應高度。spa
理論上是能夠經過已知的完整的Constraints和view的屬性來計算高度的,咱們能夠經過systemLayoutSizeFittingSize:
方法來獲取計算出來cell的size,咱們知道cell的高度須要在tableView的代理方法tableView:heightForRowAtIndexPath:
中實現的,那麼咱們考慮從如下兩點來作:設計
經過建立一個額外的cell專門用來計算其高度3d
由於計算須要佈局,因此儘可能讓其只計算一次,計算完能夠將高度保存起來代理
基於這兩個要點,咱們能夠嘗試以下(僞代碼):
- (CGFloat)autoAdjustedCellHeightAtIndexPath:(NSIndexPath *)indexPath inTableView:(UITableView *)tableView {
CGFloat cellHeight = [self cellHeightAtIndexPath:indexPath];
if (cellHeight > 0) {
return cellHeight;
} else {
//此方法建立用於自適應的cell, 注意建立一個就夠了
UITableViewCell *cell = [self cellForTableViewAutoAdjust];
//更新cell,同cellForRow中更新一致
[self updateCell:cell]
//讓cell進行layout
[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];
cell = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(layoutGuideView.bounds));
[cell setNeedsLayout];
[cell layoutIfNeeded];
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
height += 1.0f;
//計算完後保存,避免屢次重複計算
[self saveCellHeight:height forIndexPath:indexPath];
return height;
}
}
通過測試,工做良好,在體會到這點好處以後就發現Autolayout的好處了,它實際上是讓佈局變得簡單了。
在完成這個自動適應高度的設計過程當中要注意幾點:
cell中的多行UILabel,若是其width不是固定的話(好比屏幕尺寸不一樣,width不一樣),要手動設置其
preferredMaxLayoutWidth
。 由於計算UILabel的intrinsicContentSize
須要預先肯定其width才行。要保證垂直方向上的Constraints理論上能夠計算出cell的高度,另:最好調低其中一個Constraint的優先級,避免約束髮生衝突
tableView的
dequeueReusableCellWithIdentifier
取出來的cell若是未用於tableView, 那麼它就leak了. 所以用於計算高度的cell不要今後方法獲取。
scrollView比較特殊,由於它有個contentSize的屬性。那麼在遇到scrollView時,怎麼使用Autolayout呢。其實關鍵點就一點:
ScrollView的contentSize的大小是由其subview的constraints來決定的。
知道這一點其實就夠了,那麼基於這個特性,在應用的時候要注意哪些呢?
徹底依賴scrollView來計算subview的座標的Constraints設法不行了,計算條件互相依賴的,常見的如left+right+top+bottom不行了。
要保證contentSize能夠經過subview的constraints可以計算出來。
舉個栗子:
12345678 |
[childView mas_makeConstraints:^(MASConstraintMaker *make) { make.width.mas_equalTo(scrollView.mas_width); make.height.mas_equalTo(scrollView.mas_height); make.leading.mas_equalTo(scrollView.mas_leading); make.top.mas_equalTo(scrollView.mas_top); make.bottom.mas_equalTo(scrollView.mas_bottom); make.trailing.mas_equalTo(scrollView.mas_trailing).multipliedBy(1./4.);}]; |
例子中若是scrollView的size是(100x100), 那麼contentSize即爲(400x100)
在使用Autolayout時,動畫的使用和之前也不一樣了,之前咱們是修改frame,如今咱們能夠經過修改Constraints, 而後在動畫時layoutIfNeeded
就好了。
123 |
[UIView animateWithDuration:0.2 animations:^{ [view layoutIfNeeded];}]; |
Autolayout有時在動畫時候會很方便,由於View之間的座標是相互影響的,在傳統frame中,若是改變一個view的frame,那麼可能你要更改不少view的frame,才能讓頁面顯得和諧。在Autolayout中可能只須要修改一個Constraint就能夠了,在作動畫時會很方便。
雖然Autolayout很是強大,可是在剛出現的版本IOS6上,仍是有一些坑的。在IOS6上你會發如今某些系統控件上如: UITableViewCell
, UITableView
等view上直接添加Constraints會crash。 衝突的Constraints會直接致使crash等。
在strackoverflow有回答上說明了爲何UITableViewCell
等部分系統控件上添加Constraints會crash, 即UITableViewCell
等部分控件的layoutSubviews
裏面沒有執行[super layoutSubviews]
。
因此想要使用Autolayout的同窗們,若是你要兼容IOS6的話,有些問題仍是要重視的,須要充分的測試哦。