我們在寫bounds的時候通常是
self.xxxView.bounds = CGRectMake(0,0,100,100);似乎(x, y)寫成(0, 0)是一種習慣, 也是一種比較安全的行為, 因為, 如果改變了(x, y)通常會有無法預知的事情發(fā)生, 今天就來探索下, 到底會發(fā)生些什么!
1 frame基本用法
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = UIColor.redColor;
redView.frame = CGRectMake(0, 0, 200, 200);
[self.view addSubview:redView];

沒有什么好說的, 大家都知道結果會是這樣
2初級用法
UIView *redView = [[UIView alloc] init];
redView.backgroundColor = UIColor.redColor;
redView.bounds = CGRectMake(0, 0, 200, 200);
[self.view addSubview:redView];

看到了嗎? 在不設置frame的情況下, 只設置bounds, 會讓redView的中心點和self.view的起始點重合, 這里不得不說一下錨點:
一個view的layer是有anchorPoint的, 默認情況下, anchorPoint是(0.5, 0.5), 也就是在這個view的中點. 當addSubview(如果僅僅設置了bounds)的時候, 會讓錨點和父view的起始點重合, 這也就解釋了為什么會出現(xiàn)圖2的情況. 我想對于單獨使用bounds出現(xiàn)的結果, 我已經(jīng)解釋清楚了.
3中級用法
[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設置在了(0,0,200,200) 然后又設置了bounds, 但是不改變width和height

這種情況, (-100, -100) 相當于把redView的坐標系, 也就是redView的子view(這里就是blueView了)的起始點向右下移動(100, 100), 這里的減號表示方向, point的第一個參數(shù)是左右移動, 第二個是上下移動, so, 此時藍色view認為父view(紅色view)的起始點在整個坐標系的(100, 100)位置. 所以此時設置藍色view的frame會出現(xiàn)在圖3的位置.
4高級用法
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];
此時通過給redView設置bounds, 不僅改變(x, y)還改變(width, height)這時候會出現(xiàn)什么結果呢?

輸出一下redView的frame
{{-50, -50}, {300, 300}}
起始點變成了(-50, -50)
輸出下anchorPoint
{0.5, 0.5}
錨點沒變, 但是起點變了. 說好的anchorPoint和起點重合呢? 喂, 現(xiàn)在不是單純的設置bounds啊, 你設置了frame了好不啦! 為什么會出現(xiàn)這種情況呢? 小編認為, 在單純通過設置bounds的情況下, 錨點的絕對坐標應該是{0, 0}, 但是現(xiàn)在先設置了frame又重置了bounds的寬高(注意, 這里bounds的x,y不會影響到redView的顯示), 那增加的寬高如何分配呢? 總之寬高都不能變, 還是{300, 300}, 那就確定錨點的絕對坐標就行了, 錨點最初因為設置frame(0,0,200, 200), 所以錨點的絕對坐標在{100, 100}, 因為錨點的絕對坐標是不會變的, 所以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īng)設置了frame, 然而frame并不在整個view的起點, 因為錨點(0.5, 0.5), 通過frame確定中心點, 為(120, 120), 因為錨點不動, 所以frame的范圍是{120-150, 120+150}, 所以frame={{-30, -30}, {300, 300}}
看下結果

總結:
1 設置了bounds的(x, y)相當于給子view一個起點, 其中, 減號表示向正方向偏移.
2 單純設置bounds顯示出來的view的位置和錨點有關.
3 通過先設置frame再設置bounds的做法在實際開發(fā)中沒任何意義. 要知道真實frame的絕對位置, 需要通過錨點確定的原中心點的絕對位置, 然后保持中心點位置不變, 根據(jù)大小就能確定起始點了.
4 先設置bounds再設置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];
這個redView的frame是多少呢?
答案:
{{70, 70}, {100, 100}}
解讀:
frame(20, 20, 200, 200)和anchorPoint(0.5, 0.5), 確定了中心點的絕對位置 20+200*0.5 = 120, 因為錨點不動, 所以frame的范圍是{120-50, 120+50}, 所以frame={{70, 70}, {100, 100}}.