探究IOS中UI控件的位置(一):Frame、Bounds和Center

1.三個屬性的基本介紹:

? ? (1)frame:描述當(dāng)前視圖在其父視圖中的位置和大小。

? ? (2)bounds:描述當(dāng)前視圖在其自身坐標(biāo)系統(tǒng)中的位置和大小。

? ? (3)center:描述當(dāng)前視圖的中心點在其父視圖中的位置。

2.必須明確的幾個邏輯原點:

? ? ? 1.位置是相對的,想要表示一個物體的位置必須有參照系。(不同的參照系對相同位置的表示有什么不同?)

? ? ? 2.控件的原始坐標(biāo)系:默認(rèn)控件的左上角為原點,值{0,0},原點出發(fā)水平向右是x軸正方向,遞增;原點出發(fā)垂直向下是y軸正方向,遞增。

? ? ? 3.控件的bounds.origin(最初值都是{0,0})和frame.origin代表的都是控件左上角點的坐標(biāo)??梢孕薷?。(如何修改,會有什么影響?)

? ? ? 4.bounds.size和frame.size都表示控件的大小,永遠(yuǎn)一樣。(size的改變是如何影響bounds和frame的?)

? ? ? 5.bounds代表本地(控件自己的)坐標(biāo)系,frame代表父控件坐標(biāo)系。坐標(biāo)必須在同一個坐標(biāo)系中才能比較。

3.探索bounds和frame的區(qū)別和聯(lián)系

? ? ? 一般大家對frame的改變和影響比較熟悉,但是對bounds改變比較陌生。所以,下面就對父控件、子控件的bounds.origin和bounds.size分為四種情況進行組合變換來探究。通過setBounds方法來改變bounds值。

- (void)viewDidLoad {

[super viewDidLoad];

//添加父控件orangeView

UIView * orangeView = [[UIView alloc]initWithFrame:CGRectMake(100, 100, 200, 200)];

orangeView.backgroundColor = [UIColor orangeColor];

[self.view addSubview:orangeView];

//添加子控件yellowView

UIView * yellowView = [[UIView alloc]initWithFrame:CGRectMake(20, 20, 100, 100)];

yellowView.backgroundColor = [UIColor yellowColor];

[orangeView addSubview:yellowView];

}

輸出bounds和frame值:

orangeView: bounds:{{0, 0}, {200, 200}}--frame:{{100, 100}, {200, 200}};

yellowView: bounds:{{0, 0}, {100, 100}}--frame:{{20, 20}, {100, 100}}。

圖 3.0 ?添加兩個控件

3.1 保持bounds.size不變,只改變bounds.origin

?3.1.1 父控件:

[orangeView setBounds:CGRectMake(-30, -30, 200, 200)];

? ? 輸出值:

orangeView: bounds:{{-30, -30}, {200, 200}}--frame:{{100, 100}, {200, 200}};

yellowView: bounds:{{0, 0}, {100, 100}}--frame:{{20, 20}, {100, 100}}。

? ? ? 從輸出結(jié)果可以得出:父控件的bounds值變?yōu)樾薷暮蟮闹?,frame不變;子控件bounds值不變(意料之中),值得注意的是,雖然子控件的位置移動了(相對于屏幕,示例程序是向右下方移動;相對于父控件的話,其實子控件位置不變,因為frame不變),但是子控件的frame不變。(父控件通過改變自身的bounds.origin值(自身坐標(biāo)體系)抵消了子控件位移造成的frame.origin的改變(子控件的frame和父控件的bounds在同一個坐標(biāo)體系中,因此可以互相抵消))

圖 3.1 ?只改變父控件的bounds.origin

? 3.1.2 子控件:

[yellowView setBounds:CGRectMake(-30, -30, 100, 100)];

? ? 輸出值:

orangeView: bounds:{{0, 0}, {200, 200}}--frame:{{100, 100}, {200, 200}};

yellowView: bounds:{{-30, -30}, {100, 100}}--frame:{{20, 20}, {100, 100}}。

? ? ? 從輸出結(jié)果可以得出:父控件的frame和bounds值都不變,子控件只有bounds變?yōu)樾薷暮蟮闹?,frame值不變,子控件位置也不變。

? ? ? 小結(jié):從3.1.1和3.1.2的情況可以分析出:只要bounds值的origin被修改,size值不變,此時無論父控件還是子控件,只有被修改的bounds值會變?yōu)樾薷闹?,其他的值不變。但要注意:修改父控件的bounds值的origin值會導(dǎo)致子控件的位置改變(相對于屏幕)。

3.2 保持bounds.origin不變,只改變bounds.size

3.2.1 父控件

[orangeView setBounds:CGRectMake(0, 0, 250, 250)];

? ? 輸出值:

orangeView: bounds:{{0, 0}, {250, 250}}--frame:{{75, 75}, {250, 250}};

yellowView: bounds:{{0, 0}, {100, 100}}--frame:{{20, 20}, {100, 100}}。

? ? ? 從輸出結(jié)果可以得出:父控件的bounds值變?yōu)樾薷闹担琭rame值發(fā)生改變;子控件的bounds和frame不變。父控件的圖形變換規(guī)律是:以變換前的center為中心,左右、上下等距離擴大或縮小。因此,假設(shè)原子父控件的frame = {{x, y}, {w, h}},修改后的父控件bounds = {{0, 0}, {w1, h1}},那么變換后的frame = {{x-(w1-w)/2, y-(h1-h)/2}, {w1, h1}};子控件的位置(相對于父控件)不變,因為frame沒變。(圖中的綠色控件是父控件原來的位置,作為對照)

圖 3.2 ?只改變父控件的bounds.size

3.2.2 子控件

[yellowView setBounds:CGRectMake(0, 0, 250, 250)];

? ? 輸出值:

bounds:{{0, 0}, {200, 200}}--frame:{{100, 100}, {200, 200}};

yellowView: bounds:{{0, 0}, {250, 250}}--frame:{{-55, -55}, {250, 250}}

? ? ? 從輸出結(jié)果可以得出:子控件的bounds值變?yōu)樾薷闹?,frame值發(fā)生改變;父控件的bounds和frame不變。子控件的圖形變換規(guī)律和3.2.1中子控件一樣;子控件位置(相對于父控件)改變,因為frame變了。

? ? ? 小結(jié):從3.2.1和3.2.2的情況可以分析出::只要bounds值的size被修改,origin值不變,此時無論父控件還是子控件,被修改控件的bounds值變?yōu)樾薷闹?,frame值也會改變(計算公式如上),其他的值不變。 ?

3.3 同時改變bounds.origin和bounds.size

? ? ? 由3.2和3.3分析可以推測出結(jié)果(已驗證):

? ? ? 1.父控件bounds和frame改變,子控件位置改變(相對于屏幕)。

圖3.3 ?改變父控件的bounds.size和bounds.origin

? ? ? 2.和3.2.2的到的結(jié)果相同。

? ? ? 小結(jié):bounds.size的改變要優(yōu)先于bounds.origin改變進行處理。

綜述:

? ? 1.bounds.size改變時,當(dāng)前控件的frame值改變,bounds值變?yōu)楦淖兒蟮闹?,但不影響其他控件兩個參數(shù)值。

? ? 2.bounds.origin改變時,當(dāng)前控件的frame值不變,bounds值變?yōu)楦淖兒蟮闹?,但不影響其他控件兩個參數(shù)值。

? ? 3.bounds.size的改變要優(yōu)先于bounds.origin改變進行處理。

? ? 4.控件的bounds.size或bounds.origin的改變,只要改變了坐標(biāo)系,在同一個坐標(biāo)系中的其他的控件的位置(相對于屏幕)也會受到影響。

? ?5.以上規(guī)律對于控件是子控件或是父控件無需考慮。

4 應(yīng)用場景

? ? ?蘋果官方控件UITableView和UICollectionView就有很好的利用綜述中第4點的特性來改變cell的移動的。UITableView或UICollectionView相當(dāng)于父控件,cell相當(dāng)于子控件,當(dāng)滑動屏幕的時候,不斷地改變tableview或collectionview的bounds.origin,從而使所有的cell相對于屏幕的位置發(fā)生變化,產(chǎn)生向上或向下滾動的效果,而cell的frame并沒有發(fā)生改變,這樣就不用在滑動過程中重新計算cell的frame值。

參考文章:

? ? 1.深入探究frame和bounds的區(qū)別以及setbounds使用 - CocoaChina_讓移動開發(fā)更簡單;

? ? 2.詳解UIView的frame、bounds和center屬性 - 移動開發(fā) - ITeye技術(shù)網(wǎng)站。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容