iOS開發筆記(四):frame與bounds的區別詳解

相信你們學習iOS視圖部分的時候,跟它倆沒少糾纏,尤爲是bounds不少朋友都糊了,bounds確實比較難理解。這兩個概念很重要,由於它們是奠基整個視圖層次結構的基礎。因此咱們須要瞭解的透徹一點。源代碼git

首先,咱們來看一下iOS特有的座標系,在iOS座標系中以左上角爲座標原點,往右爲X正方向,往下是Y正方向以下圖:github

iOS座標系

bounds和frame都是屬於CGRect類型的結構體,系統的定義以下,包含一個CGPoint(起點)和一個CGSize(尺寸)子結構體。學習

struct CGRect {
	CGPoint origin;
	CGSize size;
};
複製代碼

origin決定了view的起點,size決定View的尺寸。spa

1.frame

frame是每一個view必備的屬性,表示view在父view座標系統中的位置和大小,參照點是父視圖的座標系統。code

示例代碼:cdn

UIView *viewA = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 300, 300)];
[viewA setBackgroundColor:[UIColor blueColor]];
[self.view addSubview:viewA];
NSLog(@"viewA - %@",NSStringFromCGRect(viewA.frame));

UIView *viewB = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 200, 200)];
[viewB setBackgroundColor:[UIColor yellowColor]];
[viewA addSubview:viewB];
NSLog(@"viewB - %@",NSStringFromCGRect(viewB.frame));

UIView *viewC = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
[viewC setBackgroundColor:[UIColor redColor]];
[self.view addSubview:viewC];
NSLog(@"viewC - %@",NSStringFromCGRect(viewC.frame));
複製代碼

打印結果:blog

2018-01-14 21:35:16.196389+0800 frame & bounds[1485:121325] viewA - {{50, 50}, {300, 300}}
2018-01-14 21:35:16.196647+0800 frame & bounds[1485:121325] viewB - {{50, 50}, {200, 200}}
2018-01-14 21:35:16.196802+0800 frame & bounds[1485:121325] viewC - {{100, 100}, {200, 200}}
複製代碼

效果圖:get

frame

以上能夠看出,viewB和viewC的起點重合,可是從打印結果來看,viewB的起點爲(50,50),而viewCde起點爲(100,100)。緣由就是frame中的位置是以父視圖的座標系爲標準來肯定當前視圖的位置,viewB的父視圖爲viewA,viewC的父視圖爲self.view,而因爲viewA的起點爲(50,50),因此viewB與viewC起點纔會重合。it

2.bounds

bounds也是每一個view都有的屬性,這個屬性咱們通常不進行設置,表示view在本地座標系統中的位置和大小。參照點是本地座標系統。若是咱們對上例打印bounds,將會獲得如下結果:io

2018-01-14 22:03:44.385207+0800 frame & bounds[1635:140821] viewA - {{0, 0}, {300, 300}}
2018-01-14 22:03:44.385482+0800 frame & bounds[1635:140821] viewB - {{0, 0}, {200, 200}}
2018-01-14 22:03:44.385646+0800 frame & bounds[1635:140821] viewC - {{0, 0}, {100, 100}}
複製代碼

由於咱們並無設置bounds值,那麼,bounds到底有什麼做用呢。這裏強調,每一個視圖都有本身的座標系,且這個座標系默認以自身的左上角爲座標原點,全部子視圖以這個座標系的原點爲基準點。bounds的位置表明的是子視圖看待當前視圖左上角的位置,bounds的大小表明當前視圖的大小。原則以下:

  • 更改bounds中的位置對於當前視圖沒有影響,至關於更改了當前視圖的座標系,對於子視圖來講當前視圖的左上角已經再也不是(0,0), 而是改變後的座標,座標系改了,那麼全部子視圖的位置也會跟着改變。
  • 更改bounds的大小,bounds的大小表明當前視圖的長和寬,修改長寬後,中心點繼續保持不變, 長寬進行改變,經過bounds修改長寬看起來就像是以中心點爲基準點對長寬兩邊同時進行縮放。

如下給出例子詳細討論。

3.二者的區別

3.1 origin的區別

以下圖:

frame&bounds 1

此時,若是咱們把ViewA的bounds改成(0,100),結果以下:

frame&bounds 2

咱們始終要清楚,bounds的位置表明的是子視圖看待當前視圖左上角的位置。 bounds遵照的原則一中,更改bounds中的位置對於當前視圖(ViewA)沒有影響,至關於更改了ViewA的座標系,可是子視圖(ViewB)不一樣,對於ViewB來講ViewA的左上角已經再也不是(0,0), 而是(0,100),因此對於ViewB來講,ViewA座標系的原點實際上是在紅色箭頭所指處的上方100處,而此時ViewB的frame.origin爲(200,100),因此ViewB的上邊與ViewA上邊重合。

若是咱們更改ViewA的bounds爲(200,0),同理(能夠本身思考試試),結果以下:

frame&bounds 3

3.2 size的區別

frame的size直接決定了view的大小,而bounds的size修改後,view的中心點不變,長寬以中心點進行縮放。

以下例:

UIView *viewA = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 240)];
[viewA setBackgroundColor:[UIColor grayColor]];
[self.view addSubview:viewA];

UIView *viewB = [[UIView alloc] initWithFrame:CGRectMake(100, 50, 160, 120)];
[viewB setBackgroundColor:[UIColor blueColor]];
[viewA addSubview:viewB];

//viewB設置size(320,160)
[viewB setBounds:CGRectMake(0, 0, 320, 240)];
複製代碼

結果以下:

未設置size

已設置size

第二個圖爲設置了size以後的結果,viewB左上點距離viewA顯然不爲(100,50),而是進行了基於viewB視圖中心點的縮放操做。

4.總結

  • frame無論對於位置仍是大小,改變的都是本身自己。
  • frame的位置是以父視圖的座標系爲參照,從而肯定當前視圖在父視圖中的位置。
  • frame的大小改變時,當前視圖的左上角位置不會發生改變,只是大小發生改變。
  • bounds改變位置時,改變的是子視圖的位置,自身沒有影響;其實就是改變了自己的座標系原點,默認自己座標系的原點是左上角。
  • bounds的大小改變時,當前視圖的中心點不會發生改變,當前視圖的大小發生改變,看起來效果就想縮放同樣。

5.參考

相關文章
相關標籤/搜索