簡體   English   中英

UIView框架,邊界和中心

[英]UIView frame, bounds and center

我想知道如何以正確的方式使用這些屬性。

據我所知, frame可以從我正在創建的視圖的容器中使用。 它設置相對於容器視圖的視圖位置。 它還設置該視圖的大小。

也可以從我正在創建的視圖的容器中使用center 此屬性更改視圖相對於其容器的位置。

最后, bounds是相對於視圖本身。 它會更改視圖的可繪制區域。

你能提供關於framebounds之間關系的更多信息嗎? clipsToBoundsmasksToBounds屬性怎么樣?

由於我問過的問題已多次出現,我將提供詳細的答案。 如果您想添加更多正確的內容,請隨意修改它。

首先回顧一下這個問題:框架,邊界和中心以及它們之間的關系。

框架視圖的frameCGRect )是其超superview坐標系中矩形的位置。 默認情況下,它從左上角開始。

邊界視圖boundsCGRect )在其自己的坐標系中表示視圖矩形。

中心 A center是以超superview的坐標系表示的CGPoint ,它確定視圖的精確中心點的位置。

UIView +位置開始,這些是之前屬性中的關系(它們在代碼中不起作用,因為它們是非正式方程式):

  • frame.origin = center - (bounds.size / 2.0)

  • center = frame.origin + (bounds.size / 2.0)

  • frame.size = bounds.size

注意:如果旋轉視圖,則這些關系不適用。 有關詳細信息,我建議您查看以下基於斯坦福CS193p課程的廚房抽屜 圖片 積分歸@Rhubarb所有

框架,邊界和中心

使用frame可以在其superview重新定位和/或調整視圖大小。 通常可以在superview ,例如,在創建特定子視圖時。 例如:

// view1 will be positioned at x = 30, y = 20 starting the top left corner of [self view]
// [self view] could be the view managed by a UIViewController
UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(30.0f, 20.0f, 400.0f, 400.0f)];    
view1.backgroundColor = [UIColor redColor];

[[self view] addSubview:view1];

當您需要在view內繪制坐標時,通常會引用bounds 一個典型的例子可能是在view繪制一個子視圖作為第一個插圖。 繪制子視圖需要知道超級視圖的bounds 例如:

UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(50.0f, 50.0f, 400.0f, 400.0f)];    
view1.backgroundColor = [UIColor redColor];

UIView* view2 = [[UIView alloc] initWithFrame:CGRectInset(view1.bounds, 20.0f, 20.0f)];    
view2.backgroundColor = [UIColor yellowColor];

[view1 addSubview:view2];

更改視圖的bounds時會發生不同的行為。 例如,如果更改bounds size ,則frame更改(反之亦然)。 變化發生在視圖的center附近。 使用下面的代碼,看看會發生什么:

NSLog(@"Old Frame %@", NSStringFromCGRect(view2.frame));
NSLog(@"Old Center %@", NSStringFromCGPoint(view2.center));    

CGRect frame = view2.bounds;
frame.size.height += 20.0f;
frame.size.width += 20.0f;
view2.bounds = frame;

NSLog(@"New Frame %@", NSStringFromCGRect(view2.frame));
NSLog(@"New Center %@", NSStringFromCGPoint(view2.center));

此外,如果更改bounds origin ,則更改其內部坐標系的origin 默認情況下, origin位於(0.0, 0.0) (左上角)。 例如,如果更改view1origin ,則可以看到(如果需要,請注釋前面的代碼),現在view2左上角觸及view1 動機很簡單。 你說view1它的左上角現在位於(20.0, 20.0)位置(20.0, 20.0)但由於view2frame origin是從(20.0, 20.0) ,它們將重合。

CGRect frame = view1.bounds;
frame.origin.x += 20.0f;
frame.origin.y += 20.0f;
view1.bounds = frame; 

origin表示view在其超superview中的位置,但描述了bounds中心的位置。

最后, boundsorigin不是相關的概念。 兩者都允許導出視圖的frame (參見前面的等式)。

View1的案例研究

以下是使用以下代碼段時發生的情況。

UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(30.0f, 20.0f, 400.0f, 400.0f)];
view1.backgroundColor = [UIColor redColor];

[[self view] addSubview:view1];

NSLog(@"view1's frame is: %@", NSStringFromCGRect([view1 frame]));
NSLog(@"view1's bounds is: %@", NSStringFromCGRect([view1 bounds]));
NSLog(@"view1's center is: %@", NSStringFromCGPoint([view1 center]));

相對的形象。

在此輸入圖像描述

相反,如果我更改[self view]界限,如下所示會發生什么。

// previous code here...
CGRect rect = [[self view] bounds];
rect.origin.x += 30.0f;
rect.origin.y += 20.0f;
[[self view] setBounds:rect];

相對的形象。

在此輸入圖像描述

在這里你要說[self view]它的左上角現在位於(30.0,20.0)位置,但由於view1的幀起點從(30.0,20.0)開始,它們將重合。

其他參考 (如果需要,可與其他參考資料一起更新)

關於clipsToBounds (源Apple文檔)

將此值設置為YES會導致子視圖被剪切到接收器的邊界。 如果設置為NO,則不會剪切其幀超出接收器可見邊界的子視圖。 默認值為NO。

換句話說,如果視圖的frame(0, 0, 100, 100) 0,0,100,100 (0, 0, 100, 100)並且其子視圖是(90, 90, 30, 30) 90,90,30,30 (90, 90, 30, 30) ,您將只看到該子視圖的一部分。 后者不會超過父視圖的范圍。

masksToBounds相當於clipsToBounds 而不是UIView ,此屬性應用於CALayer 在引擎蓋下, clipsToBounds調用masksToBounds 如需進一步參考,請查看UIView的clipsToBounds和CALayer的masksToBounds之間的關系如何?

這個問題已經有了一個很好的答案,但我想補充一些更多的圖片。 我的完整答案就在這里。

為了幫助我記住框架 ,我想到了牆上的相框 就像圖片可以移動到牆上的任何地方一樣,視圖框架的坐標系是超視圖。 (wall = superview,frame = view)

為了幫助我記住邊界 ,我想到了籃球場的界限 籃球就在球場內的某個地方,就像視線邊界的坐標系在視野內一樣。 (court = view,basketball / players =視圖內容)

與框架一樣, view.center也在superview的坐標中。

框架與邊界 - 示例1

黃色矩形表示視圖的框架。 綠色矩形表示視圖的邊界。 兩個圖像中的紅點表示幀的原點或坐標系內的邊界。

Frame
    origin = (0, 0)
    width = 80
    height = 130

Bounds 
    origin = (0, 0)
    width = 80
    height = 130

在此輸入圖像描述


例2

Frame
    origin = (40, 60)  // That is, x=40 and y=60
    width = 80
    height = 130

Bounds 
    origin = (0, 0)
    width = 80
    height = 130

在此輸入圖像描述


例3

Frame
    origin = (20, 52)  // These are just rough estimates.
    width = 118
    height = 187

Bounds 
    origin = (0, 0)
    width = 80
    height = 130

在此輸入圖像描述


例4

這與示例2相同,除了這次顯示視圖的整個內容,如果它沒有被剪切到視圖的邊界,它將看起來像。

Frame
    origin = (40, 60)
    width = 80
    height = 130

Bounds 
    origin = (0, 0)
    width = 80
    height = 130

在此輸入圖像描述


例5

Frame
    origin = (40, 60)
    width = 80
    height = 130

Bounds 
    origin = (280, 70)
    width = 80
    height = 130

在此輸入圖像描述

再次,請參閱此處獲取更多詳細信息的答案。

我發現這個圖像最有助於理解框架,邊界等。

在此輸入圖像描述

另請注意,旋轉圖像時frame.size != bounds.size

我想如果你從CALayer的角度考慮它,一切都會更清楚。

Frame根本不是視圖或圖層的獨特屬性,它是一個虛擬屬性,根據邊界,位置( UIView的中心)和變換計算。

所以基本上如何通過這三個屬性(和anchorPoint)真正決定圖層/視圖布局,並且這三個屬性中的任何一個都不會更改任何其他屬性,例如更改變換不會更改邊界。

這篇文章的詳細解釋有很好的答案。 我只是想提一下,在WWDC 2011視頻中,有關於Frame,Bounds,Center,Transform,Bounds Origin的含義的視覺表示的另一種解釋,從@ 4:22到20:10開始了解UIKit Rendering

閱讀完上述答案后,在此添加我的解釋。

假設在線瀏覽, 網頁瀏覽器是決定顯示網頁的位置和大小的frame 瀏覽器的滾動條是你的bounds.origin ,決定顯示哪個網頁部分。 bounds.origin很難理解。 學習的最佳方法是創建單視圖應用程序,嘗試修改這些參數並查看子視圖的更改方式。

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(100.0f, 200.0f, 200.0f, 400.0f)];
[view1 setBackgroundColor:[UIColor redColor]];

UIView *view2 = [[UIView alloc] initWithFrame:CGRectInset(view1.bounds, 20.0f, 20.0f)];
[view2 setBackgroundColor:[UIColor yellowColor]];
[view1 addSubview:view2];

[[self view] addSubview:view1];

NSLog(@"Old view1 frame %@, bounds %@, center %@", NSStringFromCGRect(view1.frame), NSStringFromCGRect(view1.bounds), NSStringFromCGPoint(view1.center));
NSLog(@"Old view2 frame %@, bounds %@, center %@", NSStringFromCGRect(view2.frame), NSStringFromCGRect(view2.bounds), NSStringFromCGPoint(view2.center));

// Modify this part.
CGRect bounds = view1.bounds;
bounds.origin.x += 10.0f;
bounds.origin.y += 10.0f;

// incase you need width, height
//bounds.size.height += 20.0f;
//bounds.size.width += 20.0f;

view1.bounds = bounds;

NSLog(@"New view1 frame %@, bounds %@, center %@", NSStringFromCGRect(view1.frame), NSStringFromCGRect(view1.bounds), NSStringFromCGPoint(view1.center));
NSLog(@"New view2 frame %@, bounds %@, center %@", NSStringFromCGRect(view2.frame), NSStringFromCGRect(view2.bounds), NSStringFromCGPoint(view2.center));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM