AutoLayout學(xué)習(xí)


iOS布局方式的演變

  • 使用Rect的frame布局方式
  • autoresizingMask方式
  • AutoLayout
  • SizeClass

AutoLayout深入淺出前傳

Frame布局
通過原點和長寬來確定View的展示

布局代碼:

UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 300, 300)];
view.backgroundColor = [UIColor lightGrayColor];

UIView *subView1 = [[UIView alloc]initWithFrame:CGRectMake(10, 10, 100, 100)];
[view addSubview:subView1];

[self.view addSubview:view];
  • 所有View的frame由Controller的rootView大小確定
  • rootView大小由Controller根據(jù)分辨率自動確定
    所以subView布局相對于parentView一層一層盆偿,利用parentView的長寬來確定尺寸和位置锡移,多個并列的視圖同時添加到一個parentView時壁酬,需要設(shè)計多個subView的比例巷查,確定邊界

平時開發(fā)常用的做法:

  1. 在View布局時,傳入一個固定寬度的pViewSize,該size的高度為0
  2. 布局View的subView,傳入一定一個固定寬度伍纫,高度為0的size,重復(fù)步驟1
  3. 在葉子節(jié)點View 上昂芜,算出高度莹规,改變pViewSize的height值
- (void)setupCellSubsNew:(UIView *)viewParent inSize:(CGSize *)pViewSize indexPath:(NSIndexPath *)indexPath
{
    // 子窗口高寬
    NSInteger spaceXStart = 10
    NSInteger spaceXEnd = pViewSize->width;
    NSInteger spaceYStart = 8;
    
    CGSize viewC1Size = CGSizeMake(spaceXEnd - spaceXStart, 0);
    // 創(chuàng)建View
    if (viewParent != nil)
    {
        if (_viewC1 == nil)
        {
            _viewC1 = [[UIView alloc] initWithFrame:CGRectZero];
            [_viewC1 setBackgroundColor:[UIColor clearColor]];
            [self.cardBackgroundView addSubview:_viewC1];
        }
        
        [_viewC1 setFrame:CGRectMake(spaceXStart, spaceYStart, viewC1Size.width, viewC1Size.height)];
        // 創(chuàng)建V子界面
        [self setupCellVendorC1SubsNew:_viewC1 inSize:&viewC1Size];
    }
    else
    {
        [self setupCellVendorC1SubsNew:nil inSize:&viewC1Size];
    }
    spaceYStart += viewC1Size.height;
    // 調(diào)整間距
    spaceYStart += 8;
    pViewSize->height = spaceYStart;
}


- (void)setupCellVendorC1SubsNew:(UIView *)viewParent inSize:(CGSize *)pViewSize
{
    // 子窗口高寬
    NSInteger spaceYStart = 0;
    NSInteger spaceXStart = 0;

    CGSize viewC1R2Size = CGSizeMake(pViewSize->width, 0);    
    
    // 創(chuàng)建View
    if (viewParent != nil)
    {
        [_viewC1R2 removeFromSuperview];   
        _viewC1R2 = [[UIView alloc] initWithFrame:CGRectZero];
        [viewParent addSubview:_viewC1R2];
        
        [self setupCellVendorC1R2Subs:_viewC1R2 inSize:&viewC1R2Size labels:labels lineCount:lineCount];
        [_viewC1R2 setFrame:CGRectMake(spaceXStart, spaceYStart, viewC1R2Size.width, viewC1R2Size.height)];
    }
    else
    {
        [self setupCellVendorC1R2Subs:nil inSize:&viewC1R2Size labels:labels lineCount:lineCount];
    }
    if (viewC1R2Size.height > 0)
    {
        spaceYStart += viewC1R2Size.height;
    }
    
    // 設(shè)置父窗口尺寸
    spaceXStart += viewC1R2Size.width;
    pViewSize->height = spaceYStart;
    pViewSize->width = spaceXStart;
    if (viewParent != nil)
    {
        [viewParent setSize:CGSizeMake(spaceXStart, subsHeight)];
    }
}

autoresizingMask
解決不同屏幕下布局問題,如:橫屏泌神、豎屏的切換時良漱,要么在旋轉(zhuǎn)事件中重新對視圖進行布局調(diào)整舞虱,要么就使用autoresizingMask來解決

UIView *view = [[UIView alloc]initWithFrame:CGRectMake(10, 10, self.view.bounds.size.width-10*2, 100)];
view.backgroundColor = [UIColor lightGrayColor];
[self.view addSubview:view];

view.autoresizingMask = UIViewAutoresizingFlexibleWidth;

AutoLayout
Autolayout是XCode6開始引入的專門用來進行UI界面布局的技術(shù)一種布局技術(shù),用來取代Frame布局在遇見屏幕尺寸多重多樣的不足
通過控件之間的相互依賴確定View的位置和大小

SizeClass
size class是iOS8引入的概念债热,不同分辨率設(shè)備太多砾嫉,如果按固有的布局方式來進行調(diào)整,工作量會越來越大窒篱,工作越來越繁瑣焕刮,從而Apple簡化了分辯率的概念,將尺寸抽象為Compact墙杯、Regular配并、Any(緊湊、正常高镐、任意)三種情況

AutoLayout的使用

使用方式:

  • Xib或StoryBoard
  • NSLayoutConstraint約束設(shè)置
  • VFL約束設(shè)置
  • masonry設(shè)置約束

NSLayoutConstraint設(shè)置

+(instancetype)constraintWithItem:(id)view1 
                        attribute:(NSLayoutAttribute)attr1
                        relatedBy:(NSLayoutRelation)relation
                           toItem:(nullable id)view2 
                        attribute:(NSLayoutAttribute)attr2
                       multiplier:(CGFloat)multiplier
                         constant:(CGFloat)c;

約束條件滿足:view1.attr1 = view2.attr2 * multiplier + constant
NSLayoutAttribute:表示View的Top溉旋、bottom、Left嫉髓、Right等特性
NSLayoutRelation:表示>=观腊、=、<=

VFL約束設(shè)置
VFL把水平與垂直方向的約束用字符串一并表達出來算行,而不是一個一個的添加

+ (NSArray<NSLayoutConstraint *> *)constraintsWithVisualFormat:(NSString *)format
                                                       options:(NSLayoutFormatOptions)opts 
                                                       metrics:(nullable NSDictionary<NSString *,id> *)metrics 
                                                         views:(NSDictionary<NSString *, id> *)views;

format:VFL語句
opts:View之間的對齊方式
metrics:字典梧油,key為VFL中出現(xiàn)的常量,value為常量表示的值州邢,一定為NSNumber類型
views:字典儡陨,key為VFL中出現(xiàn)的View,value為實際的View

VFL語句示例:

NSString *hFlightInfoVFL = @"H:|[_flightInfoLabel]|";
NSString *vFlightInfoVFL = @"V:[_depAirportLabel]-margin-[_flightInfoLabel]|";

水平方向上:_flightInfoLabel與父View的間距為0
垂直方向上:_flightInfoLabel的頂部與_depAirportLabel底部的間距為margin

NSString *hArrowLineVFL = @"H:[_depTimeLabel]-[_arrowLineView(>=100)]";
NSString *vArrowLineVFL = @"V:[_arrowLineView(0.5)]";

水平方向上:_depTimeLabel的右邊與_arrowLineView的左邊間距為0量淌,_arrowLineView的寬度最小為100
垂直方向上:_arrowLineView的高度為0.5

AutoLayout的性能

  • AutoLayout中每一個約束都是一個簡單的線性等式或不等式
  • 布局系統(tǒng)在最后仍然需要通過frame來進行
    相比frame布局系統(tǒng)骗村,AutoLayout增加了約束計算過程

使用 Cassowary 算法解決約束問題就是對線性等式或不等式求解,所以其時間復(fù)雜度就是多項式時間的呀枢,所以View越多胚股,約束越多,性能損耗越大

AutoLayout與TableViewCell高度計算

iOS7 + frame的布局方式:

  1. heightForRowAtIndexPath:中算出高度
  2. cellForRowAtIndexPath中創(chuàng)建cell并布局
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    [self configureCell:cell atIndexPath:indexPath];
    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    [self configureCell:_baseCell atIndexPath:indexPath];
    [_baseCell layoutSubviews];
    CGFloat height = [_baseCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
    return height;
}

iOS8高度估算 + AutoLayout布局:
iOS8中UITableViewCell的高度引入自適應(yīng)功能
iOS8中執(zhí)行順序:

  1. estimatedHeight預(yù)估高度
  2. cellForRow創(chuàng)建cell并布局
  3. heightForRow返回高度

若heightForRow返回了高度裙秋,則預(yù)估高度將作廢信轿,系統(tǒng)將使用heightForRow返回的值

_tableView.rowHeight = UITableViewAutomaticDimension;
_tableView.estimatedRowHeight = 70.0;

如果UITableView每行內(nèi)容變化很大,行高差別很大残吩,那我們可以使用以下方法為每一行設(shè)置各不相同的預(yù)估值。

- (void)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
    if(indexPath.row == 0) {
        return 40;
    }
    else if(indexPath.row = 2) {
        return 75;
    }
    return 44;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (IS_IOS8_OR_ABOVE) {
            return UITableViewAutomaticDimension;
    }
}

AutoLayout的優(yōu)缺點:
優(yōu)點:

  1. UI布局與數(shù)據(jù)處理分離
  2. 使用TableViewCell中避免了復(fù)雜的高度計算
  3. cell復(fù)用不用過多考慮子視圖是否需要hidden

缺點:

  1. 布局邏輯并沒有比使用frame更清晰倘核,代碼量也并沒有減少泣侮,(更適合與Xib搭配)
  2. 需要維護大量的NSLayoutConstraint實例和邏輯
  3. 復(fù)雜的布局效果不太好實現(xiàn)

寒哥細談之AutoLayout全解
Autolayout學(xué)習(xí)筆記
IOS AutoLayout 詳解
從 AutoLayout 的布局算法談性能
Flexbox優(yōu)化
CSS核心:再說框模型
由FlexBox算法強力驅(qū)動的Weex布局引擎

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市紧唱,隨后出現(xiàn)的幾起案子活尊,更是在濱河造成了極大的恐慌隶校,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蛹锰,死亡現(xiàn)場離奇詭異深胳,居然都是意外死亡,警方通過查閱死者的電腦和手機铜犬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門舞终,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人癣猾,你說我怎么就攤上這事敛劝。” “怎么了纷宇?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵夸盟,是天一觀的道長。 經(jīng)常有香客問我像捶,道長上陕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任拓春,我火速辦了婚禮释簿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘痘儡。我一直安慰自己辕万,他們只是感情好,可當我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布沉删。 她就那樣靜靜地躺著渐尿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪矾瑰。 梳的紋絲不亂的頭發(fā)上砖茸,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天,我揣著相機與錄音殴穴,去河邊找鬼凉夯。 笑死,一個胖子當著我的面吹牛采幌,可吹牛的內(nèi)容都是我干的劲够。 我是一名探鬼主播,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼休傍,長吁一口氣:“原來是場噩夢啊……” “哼征绎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起磨取,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤人柿,失蹤者是張志新(化名)和其女友劉穎柴墩,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體凫岖,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡江咳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了哥放。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片歼指。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖婶芭,靈堂內(nèi)的尸體忽然破棺而出东臀,到底是詐尸還是另有隱情,我是刑警寧澤犀农,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布惰赋,位于F島的核電站,受9級特大地震影響呵哨,放射性物質(zhì)發(fā)生泄漏赁濒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一孟害、第九天 我趴在偏房一處隱蔽的房頂上張望拒炎。 院中可真熱鬧,春花似錦挨务、人聲如沸击你。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽丁侄。三九已至,卻和暖如春朝巫,著一層夾襖步出監(jiān)牢的瞬間鸿摇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工劈猿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拙吉,地道東北人。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓揪荣,卻偏偏與公主長得像筷黔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子仗颈,可洞房花燭夜當晚...
    茶點故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容