相信大家學習iOS檢視部分的時候,跟它倆沒少糾纏,尤其是bounds很多朋友都糊了,bounds確實比較難理解。這兩個概念很重要,因為它們是奠定整個檢視層次結構的基礎。所以我們需要了解的透徹一點。原始碼
首先,我們來看一下iOS特有的座標系,在iOS座標系中以左上角為座標原點,往右為X正方向,往下是Y正方向如下圖:
bounds和frame都是屬於CGRect型別的結構體,系統的定義如下,包含一個CGPoint(起點)和一個CGSize(尺寸)子結構體。
struct CGRect {
CGPoint origin;
CGSize size;
};
複製程式碼
origin決定了view的起點,size決定View的尺寸。
1.frame
frame是每個view必備的屬性,表示view在父view座標系統中的位置和大小,參照點是父檢視的座標系統。
示例程式碼:
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));
複製程式碼
列印結果:
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
}
}複製程式碼
效果圖:
以上可以看出,viewB和viewC的起點重合,但是從列印結果來看,viewB的起點為(50,50),而viewCde起點為(100,100)。原因就是frame中的位置是以父檢視的座標系為標準來確定當前檢視的位置,viewB的父檢視為viewA,viewC的父檢視為self.view,而由於viewA的起點為(50,50),所以viewB與viewC起點才會重合。
2.bounds
bounds也是每個view都有的屬性,這個屬性我們一般不進行設定,表示view在本地座標系統中的位置和大小。參照點是本地座標系統。如果我們對上例列印bounds,將會得到以下結果:
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的區別
如下圖:
我們始終要清楚,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),同理(可以自己思考試試),結果如下: