これらのプロパティを正しい方法で使用する方法を知りたいです。
私が理解しているように、frame
は私が作成しているビューのコンテナから使用できます。コンテナービューに対するビュー位置を設定します。そのビューのサイズも設定されます。
私が作成しているビューのコンテナからもcenter
を使用できます。このプロパティは、コンテナに対するビューの位置を変更します。
最後に、bounds
はビュー自身からの相対パスです。ビューの描画可能領域を変更します。
frame
とbounds
の関係についてもっと詳しく教えてください。 clipsToBounds
およびmasksToBounds
プロパティはどうですか?
私が尋ねた質問は何度も見られたので、私はそれについて詳細な答えを提供します。もっと正しい内容を追加したい場合は、気軽に修正してください。
まず、この問題について要約します。フレーム、境界、中心、およびそれらの関係。
フレームビューのframe
name__(CGRect
name__)は、superview
name__の座標系におけるその矩形の位置です。デフォルトでは左上から始まります。
境界ビューのbounds
name__(CGRect
name__)は、ビューの四角形を独自の座標系で表します。
中心center
name__は、CGPoint
nameの座標系で表されるsuperview
name__であり、ビューの正確な中心点の位置を決定します。
から引用UIView + positionこれらはリレーションシップです。前式のうち非公式方程式)
frame.Origin = center - (bounds.size / 2.0)
center = frame.Origin + (bounds.size / 2.0)
frame.size = bounds.size
注:ビューが回転している場合、これらの関係は適用されません。より詳しい情報は、The Kitchen Drawerから撮った以下の画像をご覧になることをお勧めします。 スタンフォードCS193pコースに基づく。クレジットは@ Rhubarbに行きます。
frame
name__を使用すると、そのsuperview
name__内でビューの位置やサイズを変更できます。たとえば、特定のサブビューを作成するときなどに、通常はsuperview
name__から使用できます。例えば:
// 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
name__内に描画するための座標が必要な場合は、通常bounds
name__を参照します。典型的な例は、最初のインセットとしてview
name__サブビュー内に描画することです。サブビューを描画するには、スーパービューのbounds
name__を知る必要があります。例えば:
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
name__を変更すると、さまざまな動作が発生します。たとえば、bounds
size
name__を変更すると、frame
name__も変更されます(その逆も同様)。変更はビューのcenter
name__を中心に行われます。以下のコードを使用して、何が起こるのか見てください。
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
name__を変更すると、その内部座標系のOrigin
name__も変更されます。デフォルトでは、Origin
name__は(0.0, 0.0)
(左上隅)にあります。たとえば、view1
のOrigin
name__を変更すると、view2
の左上隅がview1
の隅に接触していることがわかります(必要に応じて前のコードをコメントにします)。動機は非常に簡単です。 view1
にその左上隅が(20.0, 20.0)
の位置にあると言いますが、view2
のframe
Origin
name__は(20.0, 20.0)
から始まるので、それらは一致します。
CGRect frame = view1.bounds;
frame.Origin.x += 20.0f;
frame.Origin.y += 20.0f;
view1.bounds = frame;
Origin
name__は、そのview
name__内のsuperview
name__の位置を表しますが、bounds
name__センターの位置を表します。
最後に、bounds
name__とOrigin
name__は関連概念ではありません。どちらもビューのframe
name__を派生させることができます(前の式を参照)。
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
のフレームOriginは(30.0、20.0)から始まるので、それらは一致します。
追加の参照(必要に応じて他の参照で更新するため)
clipsToBounds
name__について(source Apple doc)
この値をYESに設定すると、サブビューはレシーバーの境界にクリップされます。 NOに設定すると、フレームがレシーバの表示範囲を超えて伸びるサブビューは切り取られません。デフォルト値はNOです。
つまり、ビューのframe
name__が(0, 0, 100, 100)
でそのサブビューが(90, 90, 30, 30)
の場合、そのサブビューの一部しか表示されません。後者は、親ビューの範囲を超えません。
masksToBounds
name__はclipsToBounds
name__と同等です。 UIView
name__ではなく、このプロパティはCALayer
name__に適用されます。内部では、clipsToBounds
name__はmasksToBounds
name__を呼び出します。詳細については、 を参照してください。UIViewのclipsToBoundsとCALayerのmasksToBoundsの関係はどうですか? 。
この質問にはすでに良い答えがありますが、もう少し詳しく説明します。 私の完全な答えはここにあります。
フレームを思い出すのを助けるために、私は壁の上の額縁を考えます。絵が壁のどこにでも動くことができるように、ビューのフレームの座標系はスーパービューです。 (壁=スーパービュー、フレーム=ビュー)
範囲を覚えやすくするために、私はバスケットボールコートの範囲を考えます。バスケットボールは、ビューの境界の座標系がビュー自体の中にあるように、コート内のどこかにあります。 (コート=ビュー、バスケットボール/選手=ビュー内のコンテンツ)
フレームのように、view.centerもスーパービューの座標にあります。
黄色い長方形はビューのフレームを表します。緑色の長方形はビューの境界を表します。両方の画像の赤い点は、フレームの原点またはそれらの座標系内の境界を表します。
Frame
Origin = (0, 0)
width = 80
height = 130
Bounds
Origin = (0, 0)
width = 80
height = 130
Frame
Origin = (40, 60) // That is, x=40 and y=60
width = 80
height = 130
Bounds
Origin = (0, 0)
width = 80
height = 130
Frame
Origin = (20, 52) // These are just rough estimates.
width = 118
height = 187
Bounds
Origin = (0, 0)
width = 80
height = 130
これは例2と同じですが、今回はビューの境界全体にクリップされていない場合のようにビューの内容全体が表示される点が異なります。
Frame
Origin = (40, 60)
width = 80
height = 130
Bounds
Origin = (0, 0)
width = 80
height = 130
Frame
Origin = (40, 60)
width = 80
height = 130
Bounds
Origin = (280, 70)
width = 80
height = 130
繰り返しになりますが、私の答えについては こちら をご覧ください。
この画像は、枠、境界線などを理解するのに最も役立ちます。
また、画像が回転したときのframe.size != bounds.size
にも注意してください。
CALayer
の観点から考えれば、すべてがより明確になります。
Frameは、実際にはビューやレイヤのまったく異なるプロパティではありません。境界、位置(UIView
の中心)、およびトランスフォームから計算された仮想プロパティです。
そのため、基本的にレイヤ/ビューのレイアウトはこれら3つのプロパティ(およびanchorPoint)によって実際にどのように決定されますか。また、変換を変更しても境界は変更されません。
この記事への詳しい説明と非常によい答えがあります。 WWDC 2011ビデオのFrame、Bounds、Center、Transform、Bounds Originの意味についてのビジュアル表現による別の説明があることを言及したいだけですUIKitについて理解する@ 4:22から20:10までのレンダリング
上記の答えを読んだ後、ここに私の解釈を加えます。
オンラインブラウジング、WebブラウザがWebページを表示する場所と大きさを決定するframe
であるとします。 ブラウザのスクローラは、Webページのどの部分を表示するかを決める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));