Frame布局入門看我就夠了

初識(shí)

在IOS中最常用的兩種布局方式是Frame布局和AutoLayout布局。本文主要講解Frame布局的相關(guān)知識(shí)譬涡。
Frame布局使用簡(jiǎn)單闪幽,適合初學(xué)者,可以采用手寫或者xib進(jìn)行布局涡匀,適用于比較簡(jiǎn)單的界面布局盯腌,復(fù)雜的布局如果使用Frame布局邏輯會(huì)很復(fù)雜,不利于布局和后期維護(hù)陨瘩。
Frame的數(shù)據(jù)結(jié)構(gòu)簡(jiǎn)單腕够,類型為CGRect,其中original屬性定義point舌劳,size屬性定義大小帚湘,初始化成功一個(gè)Frame布局之后,可以使用setFrame修改布局甚淡。frame的值影響自己的布局大诸,bounds只影響其子view的布局。

UIView* view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
[self.view addSubview:view];

適用場(chǎng)景

有時(shí)候會(huì)遇到一些稍微復(fù)雜度一點(diǎn)的界面布局贯卦,這時(shí)候可以使用函數(shù)或者對(duì)象封裝原生的frame布局方法资柔,好的封裝讓我們可以使用鏈?zhǔn)讲季諿^1]的方法,和更簡(jiǎn)單的方式進(jìn)行frame布局撵割。
已經(jīng)有前人實(shí)現(xiàn)了frame布局的相對(duì)布局[5]
也有三方庫(kù)支持像使用masory一樣使用frame布局[6]和[7]
但是很復(fù)雜的界面就不建議使用frame布局了贿堰,可以使用autolayout布局,當(dāng)然還有其它布局方式睁枕,這兒不討論官边。
Frame布局的效率比AutoLayout高得多,下面是他們的效率比較圖表外遇。


performance.png

圖片來(lái)源和性能分析更詳細(xì)可參考[2]

調(diào)試

可以使用系統(tǒng)自帶的debug view hierachy和第三方的Reveal查看當(dāng)前界面的布局情況注簿。

Debug view hierachy:


debug1.png

Reveal:


debug2.png

可以在lldb中使用po查看view的frame值,這也是我們調(diào)試界面布局的一個(gè)重要參考指標(biāo)跳仿,如果不能查看诡渴,需要手動(dòng)在lldb中運(yùn)行e @import UIKit,然后po就可以了菲语。(如果不清楚po是什么妄辩,需要先去看下lldb的基礎(chǔ)知識(shí))

Frame動(dòng)畫

可以通過(guò)改變frame布局的值來(lái)實(shí)現(xiàn)一些簡(jiǎn)單的動(dòng)畫,當(dāng)然這兒不使用frame是因?yàn)?br> 一般外部使用view,使用frame山上;內(nèi)部使用或者定義view眼耀,使用bounds;動(dòng)畫和旋轉(zhuǎn)一般基于center來(lái)進(jìn)行佩憾,很少通過(guò)操作frame哮伟。

[UIView animateWithDuration:0.5 animations:^{
                
       self.view.center = CGPointMake(20, 20);
                
       } completion:^(BOOL finished) {
                    
                    //do something       
 }];

Frame的本質(zhì)

每個(gè)view都有一個(gè)frame干花,這個(gè)frame實(shí)際是layer的frame,view只是透?jìng)鱢rame的值楞黄。修改view的frame布局池凄,其實(shí)修改的是layer的frame布局。
Frame屬性只是一個(gè)計(jì)算屬性鬼廓,它最后的值由bounds肿仑,anchor,position和transform這幾個(gè)實(shí)際屬性計(jì)算獲得碎税,他們之間會(huì)相互影響尤慰。具體的算法如下,參考文章[3]和參考[4]蚣录。
下面是frame計(jì)算的偽代碼


 -(CGRect)frame
{
      CGRect retValue = CGRectZero;
      if (CGAffineTransformIsIdentity(self.transform))
      { //沒(méi)有設(shè)置仿射變換的情況下
           
            //位置等于中心點(diǎn)的位置減去視圖尺寸乘以錨點(diǎn)的值割择。
            retValue.origin.x = self.center.x - self.bounds.size.width * self.layer.anchorPoint.x;
            retValue.origin.y = self.center.y - self.bounds.size.height * self.layer.anchorPoint.y;
           //尺寸等于視圖的尺寸
            retValue.size.width = self.bounds.size.width;
            retValue.size.height = self.bounds.size.height;
      }
      else
      {
            CGAffineTransform left =  CGAffineTransformMakeTranslation(-1 * self.bounds.size.width * self.layer.anchorPoint.x, -1 * self.bounds.size.height * self.layer.anchorPoint.y);
            //因?yàn)橄旅娴淖鴺?biāo)變換應(yīng)用是從(0,0)開始的,因此這里的right指定中心點(diǎn)的位置萎河,也就是下面的復(fù)合變換右乘right來(lái)實(shí)現(xiàn)位置的變換處理荔泳。
            CGAffineTransform right =  CGAffineTransformMakeTranslation(self.center.x, self.center.y);
            //整個(gè)復(fù)合變換是left 左乘 視圖的tansform屬性然后再右乘right變換。
            CGAffineTransform concat  = CGAffineTransformConcat(CGAffineTransformConcat(left, self.transform), right); 
            retValue  = CGRectApplyAffineTransform(CGRectMake(0,0,self.bounds.size.width, self.bounds.size.height), concat);
      }

    return retValue
}

立即刷新Frame

frame布局可以使用setneedlayout設(shè)置刷新布局標(biāo)志位虐杯,如果需要立即刷新調(diào)用layoutifneed方法玛歌,會(huì)立即觸發(fā)調(diào)用layoutsubviews,你可以在這個(gè)接口中做很多事擎椰,比如你可以在這個(gè)接口里面刷新它父親的布局支子。

@implementation ViewController

-(void)viewDidLayoutSubviews
{
    //Second
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    UIView* test = [[UIView alloc] initWithFrame:CGRectMake(0, 44, 20, 20)];
    test.backgroundColor = [UIColor blackColor];
    
    [self.view addSubview:test];//First
    
    [self.view layoutIfNeeded];
    
    NSLog(@"3");    //Third
}


@end

從上述代碼中的First,Second和Third可以看出執(zhí)行順序达舒。

Autoresizingmask

使用Autoresizingmask值朋,系統(tǒng)會(huì)自動(dòng)生成frame布局,并且這個(gè)布局在父view變化的時(shí)候會(huì)跟隨變化巩搏。

適配

frame布局在處理適配的問(wèn)題上比autolayout需要做更多工作昨登。frame布局在適配不同的機(jī)型上可能會(huì)出現(xiàn)很多的魔法變量,當(dāng)然可以用宏定義解決一部分問(wèn)題贯底,但是會(huì)使得后期難以維護(hù)和理解丰辣,畢竟代碼大部分時(shí)間都是用來(lái)閱讀的,所以可讀性還是很重要的禽捆。

[1] 鏈?zhǔn)讲季郑?a href="http://www.reibang.com/p/67fd5332e7b9" target="_blank">http://www.reibang.com/p/67fd5332e7b9

[2] 性能分析:https://draveness.me/layout-performance

[3] Frame計(jì)算:http://www.reibang.com/p/a12cc7356c99

[4] Frame計(jì)算:http://www.reibang.com/p/00482643234d

[5] Frame相對(duì)布局:https://github.com/huisedediao/UIView-FrameLayout

[6] Frame相對(duì)布局:http://www.reibang.com/p/d99e94e6b9f9

[7] Frame相對(duì)布局:http://www.reibang.com/p/b76947766583

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末笙什,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子胚想,更是在濱河造成了極大的恐慌琐凭,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浊服,死亡現(xiàn)場(chǎng)離奇詭異淘正,居然都是意外死亡摆马,警方通過(guò)查閱死者的電腦和手機(jī)臼闻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門鸿吆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人述呐,你說(shuō)我怎么就攤上這事惩淳。” “怎么了乓搬?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵思犁,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我进肯,道長(zhǎng)激蹲,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任江掩,我火速辦了婚禮学辱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘环形。我一直安慰自己策泣,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布抬吟。 她就那樣靜靜地躺著萨咕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪火本。 梳的紋絲不亂的頭發(fā)上危队,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音钙畔,去河邊找鬼茫陆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛刃鳄,可吹牛的內(nèi)容都是我干的盅弛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼叔锐,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼挪鹏!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起愉烙,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤讨盒,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后步责,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體返顺,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡禀苦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了遂鹊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片振乏。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖秉扑,靈堂內(nèi)的尸體忽然破棺而出慧邮,到底是詐尸還是另有隱情,我是刑警寧澤舟陆,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布误澳,位于F島的核電站,受9級(jí)特大地震影響秦躯,放射性物質(zhì)發(fā)生泄漏忆谓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一踱承、第九天 我趴在偏房一處隱蔽的房頂上張望倡缠。 院中可真熱鬧,春花似錦勾扭、人聲如沸毡琉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)桅滋。三九已至,卻和暖如春身辨,著一層夾襖步出監(jiān)牢的瞬間丐谋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工煌珊, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留号俐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓定庵,卻偏偏與公主長(zhǎng)得像吏饿,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蔬浙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

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