325

これらのプロパティを正しい方法で使用する方法を知りたいです。

私が理解frameしているように、私が作成しているビューのコンテナから使用できます。コンテナ ビューに対するビューの位置を設定します。また、そのビューのサイズも設定します。

center私が作成しているビューのコンテナからも使用できます。このプロパティは、コンテナーに対するビューの位置を変更します。

最後にbounds、ビュー自体に相対的です。ビューの描画可能領域を変更します。

frameとの関係について詳しく教えてくださいboundsclipsToBoundsmasksToBoundsプロパティはどうですか?

4

6 に答える 6

584

私が尋ねた質問は何度も見られているので、詳細な回答を提供します。より正確な内容を追加したい場合は、自由に変更してください。

最初に質問の要約: フレーム、境界、中心、およびそれらの関係。

フレームビューのframe( ) は、の座標系CGRectにおけるその長方形の位置です。superviewデフォルトでは、左上から開始されます。

境界ビューのbounds( CGRect) は、独自の座標系でビューの四角形を表します。

中心Acenterはの座標系CGPointで表されsuperview、ビューの正確な中心点の位置を決定します。

UIView + positionから取得したこれらは、前のプロパティ間の関係です (非公式の方程式であるため、コードでは機能しません)。

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

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

  • frame.size = bounds.size

注:ビューが回転している場合、これらの関係は適用されません。詳細については、スタンフォード CS193pコースに基づいてThe Kitchen Drawerから取得した次の画像をご覧になることをお勧めします。クレジットは@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)(左上隅) にあります。たとえば、originforを変更するとview1(必要に応じて前のコードをコメントしてください)、 for の左上隅がそれにview2触れていることがわかりますview1。動機は至ってシンプル。view1左上隅が の位置にあると言いますが、は から始まる(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表しますが、中心の位置を表します。viewsuperviewbounds

最後に、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 doc)

この値を YES に設定すると、サブビューがレシーバーの境界にクリップされます。NO に設定すると、フレームがレシーバーの可視境界を超えて伸びるサブビューはクリップされません。デフォルト値は NO です。

つまり、ビューframeが で(0, 0, 100, 100)、そのサブビューが(90, 90, 30, 30)である場合、そのサブビューの一部のみが表示されます。後者は、親ビューの境界を超えません。

masksToBoundsと同等clipsToBoundsです。の代わりにUIView、このプロパティは に適用されますCALayer。内部では、 をclipsToBounds呼び出しますmasksToBounds。詳細については、UIView の clipsToBounds と CALayer の maskToBounds との関係はどのようになっていますか?を参照してください。.

于 2012-07-01T14:27:48.007 に答える
141

この質問にはすでに適切な回答がありますが、さらにいくつかの写真で補足したいと思います。私の完全な答えはここにあります。

フレームを覚え やすく する ために , 壁 の 額縁 を 思い浮かべます . 写真を壁のどこにでも移動できるように、ビューのフレームの座標系がスーパービューです。(壁=俯瞰、枠=眺め)

境界を覚えやすくするために、バスケットボール コートの境界を考えます。ビューの境界の座標系がビュー自体の中にあるように、バスケットボールはコート内のどこかにあります。(court=ビュー、basketball/players=ビュー内のコンテンツ)

フレームと同様に、view.centerもスーパービューの座標にあります。

フレームと境界 - 例 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

ここに画像の説明を入力

繰り返しますが、詳細については、こちらを参照してください。

于 2015-03-08T06:11:10.990 に答える
89

この画像は、フレームや境界などを理解するのに最も役立つことがわかりました。

ここに画像の説明を入力

frame.size != bounds.sizeまた、画像を回転させる際はご注意ください。

于 2012-10-12T00:50:54.717 に答える
4

の点から考えればCALayer、すべてがより明確になると思います。

Frame は実際にはビューまたはレイヤーの個別のプロパティではなく、境界、位置 (UIViewの中心)、および変換から計算される仮想プロパティです。

したがって、基本的に、レイヤー/ビューのレイアウトが実際にこれら 3 つのプロパティ (および anchorPoint) によってどのように決定されるかが決まります。これら 3 つのプロパティのいずれも、トランスフォームを変更しても境界が変更されないように、他のプロパティを変更しません。

于 2014-10-21T05:51:34.557 に答える
0

上記の回答を読んだ後、ここに私の解釈を追加します。

オンラインでブラウジングすると仮定すると、Web ブラウザーは、Webframeページを表示する場所と大きさを決定するものです。ブラウザのスクローラbounds.originは、Web ページのどの部分を表示するかを決定します。bounds.originわかりにくいです。学習する最善の方法は、Single View Application を作成し、これらのパラメーターを変更して、サブビューがどのように変化するかを確認することです。

- (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));
于 2015-04-03T20:46:57.537 に答える