我們在寫bounds的時(shí)候通常是
self.xxxView.bounds = CGRectMake(0,0,100,100);
似乎(x, y)
寫成(0, 0)
是一種習(xí)慣, 也是一種比較安全的行為, 因?yàn)? 如果改變了(x, y)
通常會(huì)有無法預(yù)知的事情發(fā)生, 今天就來探索下, 到底會(huì)發(fā)生些什么!
1 frame基本用法
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = UIColor.redColor;
redView.frame = CGRectMake(0, 0, 200, 200);
[self.view addSubview:redView];
沒有什么好說的, 大家都知道結(jié)果會(huì)是這樣
2初級(jí)用法
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = UIColor.redColor;
redView.bounds = CGRectMake(0, 0, 200, 200);
[self.view addSubview:redView];
看到了嗎? 在不設(shè)置frame的情況下, 只設(shè)置bounds, 會(huì)讓redView的中心點(diǎn)和self.view的起始點(diǎn)重合, 這里不得不說一下錨點(diǎn):
一個(gè)view的layer是有anchorPoint的, 默認(rèn)情況下, anchorPoint是(0.5, 0.5)
, 也就是在這個(gè)view的中點(diǎn). 當(dāng)addSubview(如果僅僅設(shè)置了bounds)的時(shí)候, 會(huì)讓錨點(diǎn)和父view的起始點(diǎn)重合, 這也就解釋了為什么會(huì)出現(xiàn)圖2的情況. 我想對(duì)于單獨(dú)使用bounds出現(xiàn)的結(jié)果, 我已經(jīng)解釋清楚了.
3中級(jí)用法
[super viewDidLoad];
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = UIColor.redColor;
redView.frame = CGRectMake(0, 0, 200, 200);
redView.bounds = CGRectMake(-100, -100, 200, 200);
[self.view addSubview:redView];
UIView *blueView = [[UIView alloc] init];
blueView.backgroundColor = UIColor.blueColor;
blueView.frame = CGRectMake(0, 0, 100, 100);
[redView addSubview:blueView];
這里已經(jīng)把redView 的frame設(shè)置在了(0,0,200,200) 然后又設(shè)置了bounds, 但是不改變width和height
這種情況, (-100, -100)
相當(dāng)于把redView的坐標(biāo)系, 也就是redView的子view(這里就是blueView了)的起始點(diǎn)向右下移動(dòng)(100, 100)
, 這里的減號(hào)表示方向, point的第一個(gè)參數(shù)是左右移動(dòng), 第二個(gè)是上下移動(dòng), so, 此時(shí)藍(lán)色view認(rèn)為父view(紅色view)的起始點(diǎn)在整個(gè)坐標(biāo)系的(100, 100)
位置. 所以此時(shí)設(shè)置藍(lán)色view的frame會(huì)出現(xiàn)在圖3的位置.
4高級(jí)用法
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = UIColor.redColor;
redView.frame = CGRectMake(0, 0, 200, 200);
redView.bounds = CGRectMake(-100, -100, 300, 300);
[self.view addSubview:redView];
此時(shí)通過給redView設(shè)置bounds, 不僅改變(x, y)
還改變(width, height)
這時(shí)候會(huì)出現(xiàn)什么結(jié)果呢?
輸出一下redView的frame
{{-50, -50}, {300, 300}}
起始點(diǎn)變成了(-50, -50)
輸出下anchorPoint
{0.5, 0.5}
錨點(diǎn)沒變, 但是起點(diǎn)變了. 說好的anchorPoint和起點(diǎn)重合呢? 喂, 現(xiàn)在不是單純的設(shè)置bounds啊, 你設(shè)置了frame了好不啦! 為什么會(huì)出現(xiàn)這種情況呢? 小編認(rèn)為, 在單純通過設(shè)置bounds的情況下, 錨點(diǎn)的絕對(duì)坐標(biāo)應(yīng)該是{0, 0}
, 但是現(xiàn)在先設(shè)置了frame又重置了bounds的寬高(注意, 這里bounds的x,y不會(huì)影響到redView的顯示), 那增加的寬高如何分配呢? 總之寬高都不能變, 還是{300, 300}
, 那就確定錨點(diǎn)的絕對(duì)坐標(biāo)就行了, 錨點(diǎn)最初因?yàn)樵O(shè)置frame(0,0,200, 200)
, 所以錨點(diǎn)的絕對(duì)坐標(biāo)在{100, 100}
, 因?yàn)殄^點(diǎn)的絕對(duì)坐標(biāo)是不會(huì)變的, 所以frame的范圍是{100-300/2, 100+300/2}={-50,250}
, 所以frame={{-50, -50}, {300, 300}}
5終極玩法
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = UIColor.redColor;
redView.frame = CGRectMake(20, 20, 200, 200);
redView.bounds = CGRectMake(0, 0, 300, 300);
[self.view addSubview:redView];
如果說高級(jí)玩法還勉強(qiáng)可以接受的話, 那終極玩法純粹是作死啊, 已經(jīng)設(shè)置了frame, 然而frame并不在整個(gè)view的起點(diǎn), 因?yàn)殄^點(diǎn)(0.5, 0.5)
, 通過frame確定中心點(diǎn), 為(120, 120)
, 因?yàn)殄^點(diǎn)不動(dòng), 所以frame的范圍是{120-150, 120+150}
, 所以frame={{-30, -30}, {300, 300}}
看下結(jié)果
總結(jié):
1 設(shè)置了bounds的(x, y)
相當(dāng)于給子view一個(gè)起點(diǎn), 其中, 減號(hào)表示向正方向偏移.
2 單純設(shè)置bounds顯示出來的view的位置和錨點(diǎn)有關(guān).
3 通過先設(shè)置frame再設(shè)置bounds的做法在實(shí)際開發(fā)中沒任何意義. 要知道真實(shí)frame的絕對(duì)位置, 需要通過錨點(diǎn)確定的原中心點(diǎn)的絕對(duì)位置, 然后保持中心點(diǎn)位置不變, 根據(jù)大小就能確定起始點(diǎn)了.
4 先設(shè)置bounds再設(shè)置frame, 以frame值為最終view的frame.
思考
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = UIColor.redColor;
redView.frame = CGRectMake(20, 20, 200, 200);
redView.bounds = CGRectMake(0, 0, 100, 100);
[self.view addSubview:redView];
這個(gè)redView的frame是多少呢?
答案:
{{70, 70}, {100, 100}}
解讀:
frame(20, 20, 200, 200)
和anchorPoint(0.5, 0.5)
, 確定了中心點(diǎn)的絕對(duì)位置 20+200*0.5 = 120, 因?yàn)殄^點(diǎn)不動(dòng), 所以frame的范圍是{120-50, 120+50}
, 所以frame={{70, 70}, {100, 100}}
.