frame和bounds的區(qū)別(轉(zhuǎn)載)

原鏈接:http://www.lxweimin.com/p/964313cfbdaa

原作者:西木柚子

僅供我個人收藏學(xué)習(xí),原博主如不同意請聯(lián)系qq651263878進(jìn)行刪除,在此表示感謝以及歉意。

在iOS中我們會經(jīng)常遇到frame和bounds,這兩個概念很相似,但是也有區(qū)別。frame還好理解,但是bounds就比較容易迷惑人。我們通過實例來講解下bounds的概念,然后再看看bounds有哪些用途,這樣就可以徹底搞清楚bounds了。

frame和bounds簡介

先看一張圖:

frame: 該view在父view坐標(biāo)系統(tǒng)中的位置和大小。(參照點是,父親的坐標(biāo)系統(tǒng))

bounds:該view在本地坐標(biāo)系統(tǒng)中的位置和大小。(參照點是,本地坐標(biāo)系統(tǒng),就相當(dāng)于ViewB自己的坐標(biāo)系統(tǒng),以0,0點為起點)。

其實本地坐標(biāo)系統(tǒng)的關(guān)鍵就是要知道的它的原點(0,0)在父坐標(biāo)系統(tǒng)中的什么位置(這個位置是相對于父view的本地坐標(biāo)系統(tǒng)而言的,最終的父view就是UIWindow,它的本地坐標(biāo)系統(tǒng)原點就是屏幕的左上角了)。

通過修改view的bounds屬性可以修改本地坐標(biāo)系統(tǒng)的原點位置。

frame我相信大家都理解的比較清楚,但是bounds光是這么說估計大家都很迷糊,那么我們下面來看具體的實例。

bounds到底起什么作用

示例代碼:

UIView*view1 = [[UIViewalloc] initWithFrame:CGRectMake(200,200,100,100)];? ? view1.backgroundColor = [UIColorredColor];? ? [self.view addSubview:view1];//添加到self.viewNSLog(@"view1 frame:%@========view1 bounds:%@",NSStringFromCGRect(view1.frame),NSStringFromCGRect(view1.bounds));UIView*view2 = [[UIViewalloc] initWithFrame:CGRectMake(0,0,100,100)];? ? view2.backgroundColor = [UIColoryellowColor];? ? [view1 addSubview:view2];//添加到view1上,[此時view1坐標(biāo)系左上角起點為(-20,-20)]NSLog(@"view2 frame:%@========view2 bounds:%@",NSStringFromCGRect(view2.frame),NSStringFromCGRect(view2.bounds));

效果圖:

image

輸出日志:

image

這個是常規(guī)的場景,我相信大家都能理解。

下面我們來改變view1的bounds,代碼如下

[view1 setBounds:CGRectMake(-20,-20,200,200)];

此時顯示和輸出日志如下所示:

image

image

分析

上面設(shè)置view1的bounds的代碼起到了讓view2的位置改變的作用。為何(-20,-20)的偏移量,卻可以讓view2向右下角移動呢?

這是因為setBounds的作用是:強(qiáng)制將自己(view1)本地坐標(biāo)系的原點改為(-20,-20)。這個(-20,-20)是相對view1的父view(self.view)偏移的。也就是向左上角偏移。

那么在view1的坐標(biāo)系中(0,0)這個點是需要向右下各偏移20。

因為view1的subview(view2)的frame參照的坐標(biāo)系是父view(view1)的bounds設(shè)置的,而此時view2的frame設(shè)置為(0,0),就會導(dǎo)致view2向右下各偏移20。如上圖所示。

總結(jié)

所以,bounds的有這么一個特點:

它是參考自己坐標(biāo)系,它可以修改自己坐標(biāo)系的原點位置,進(jìn)而影響到“子view”的顯示位置。

bounds使用場景

其實bounds我們一直在使用,就是我們使用scrollview的時候。

為什么我們滾動scrollview可以看到超出顯示屏的內(nèi)容。就是因為scrollview在不斷改變自己的bounds,從而改變scrollview上的子view的frame,讓他們的frame始終在最頂級view(window)的frame內(nèi)部,這樣我們就可以始終看到內(nèi)容了。

下面通過一個具體的例子來看看:

self.imageview = [[UIImageViewalloc]initWithFrame:CGRectMake(100,0,50,1000)];self.imageview.image = [UIImageimageNamed:@"1"];self.imageview.contentMode =UIViewContentModeScaleAspectFill;self.scrollview.contentSize =self.imageview.frame.size;? ? [self.scrollview addSubview:self.imageview];

在向上滾動過程中,輸出scrollview的frame,bouns,contentoffset和子控件imageview的frame,bounds

-(void)scrollViewDidScroll:(UIScrollView*)scrollView{NSLog(@"scrollview[contentoffset:%@---frame:%@------bounds:%@",NSStringFromCGPoint(scrollView.contentOffset),NSStringFromCGRect(self.scrollview.frame),NSStringFromCGRect(self.scrollview.bounds));NSLog(@"imageview[frame:%@------bounds:%@",NSStringFromCGRect(self.imageview.frame),NSStringFromCGRect(self.imageview.bounds));}

輸出結(jié)果如下:

image

分析:

可以看到imageview的frame和bounds還有scrollview的frame是沒有改變的。唯一在不斷改變的是scrollview的contentoffset和bounds,而且兩者完全相同。

結(jié)合上面我們講的知識,就不難理解為什么scrollview要這么做了。

向上滾動scrollview,我們就不斷增加scrollview的bounds的y值,也就是不斷把scrollview的本地坐標(biāo)系原點向下偏移(相對于scrollview的父view的坐標(biāo)系,y值越大,越向下偏移)。那么此時scrollview的子控件的frame設(shè)置的(0,0)就是不斷向上偏移

假設(shè)某一時刻scrollview的坐標(biāo)系原點為(0,100),那么scrollview的(0,0)位置就是相對于坐標(biāo)系原點向上偏移100的距離,設(shè)置scrollview的子控件的frame為(0,0),就是設(shè)置子控件左上角在scrollview中的(0,0)位置,那么子控件就會向上偏移100,你也就看到scrollview的內(nèi)容(子控件)向上滾動的效果。

其實我們可以使用文章開始的例子來模式UIScrollview的滾動效果,經(jīng)過上面的分析我們知道就是通過不斷增加UIScrollview的bounds的Y值,才可以出現(xiàn)滾動效果從而顯示超出屏幕的內(nèi)容。

那么使用文章開頭的例子,我們可以不斷增加view1的bounds的y值,來看看是不是可以達(dá)到同樣的效果:view1不動,view2在不斷向上滾動

代碼如下:

UIView*view1 = [[UIViewalloc] initWithFrame:CGRectMake(100,200,200,100)];? ? view1.backgroundColor = [UIColorredColor];? ? [self.view addSubview:view1];//添加到self.viewUIView*view2 = [[UIViewalloc] initWithFrame:CGRectMake(20,0,100,1000)];? ? view2.backgroundColor = [UIColoryellowColor];? ? [view1 addSubview:view2];//添加到view1上,[此時view1坐標(biāo)系左上角起點為(-20,-20)][UIViewanimateWithDuration:3.0animations:^{? ? ? ? [view1 setBounds:CGRectMake(0,1000,200,100)];? ? }];

運(yùn)行看看,可以發(fā)現(xiàn)view1固定不動,view2在不斷向上滾動,此時的view1就相當(dāng)于UIScrollview,而view2相當(dāng)于UIScrollview上面顯示的內(nèi)容,現(xiàn)在明白了嗎?

bouns大于frame的情況

假設(shè)設(shè)置了控件的bounds大于frame,那么此時會導(dǎo)致frame被撐大,frame的x,y,width,height都會改變。

image

結(jié)論

新的frame的size等于bound的size。

新的frame.x = 舊frame.x - (bounds.size.witdh - 舊frame.size.width)/2

新的frame.y = 舊frame.y - (bounds.size.height - 舊frame.size.height)/2

bound的改變會累加

假設(shè)view1上面添加了view2,view2上面添加了view3。三個view的size都是(100,100)。

我們設(shè)置如下:

view1.bound = (0,100,100,100)

view2.bound = (0,100,100,100)

那么此時view3.frame = (0,0,100,100),view3會相對于原來沒有設(shè)置view1、view2的bound時的位置向上偏移200。

總結(jié)

frame是參考父view的坐標(biāo)系來設(shè)置自己左上角的位置。

設(shè)置bounds可以修改自己坐標(biāo)系的原點位置,進(jìn)而影響到其“子view”的顯示位置。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容