UIViewフレーム、境界および中央


320

これらのプロパティの正しい使い方を教えてください。

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

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

最後boundsに、ビュー自体に関連しています。ビューの描画可能領域を変更します。

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


1
この議論はすでにここで解決されています。そうplsはここでそれを見てか、開発者向けドキュメントがここで与えられた見ることができましたdeveloper.apple.com/library/ios/#documentation/uikit/reference/... stackoverflow.com/questions/1210047/... slideshare.net/onoaonoa/cs193p-lecture-5 -view-animation
Splendid

回答:


577

質問は何度も出てきましたので、詳しくお答えします。より正確なコンテンツを追加したい場合は、自由に変更してください。

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

フレーム AビューのframeCGRect)は、superviewの座標系における長方形の位置です。デフォルトでは左上から始まります。

境界ビューのboundsCGRect)は、ビューの長方形を独自の座標系で表します。

中心 AはcenterCGPointで表現superviewの座標系とそれがビューの正確な中心点の位置を決定します。

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)(左上隅)にあります。たとえば、originfor を変更するとview1、左上隅がに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表しviewますsuperviewが、bounds中心の位置を示します。

最後に、 boundsそしてorigin概念を関連していません。どちらも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のmasksToBoundsの関係をご覧ください。


@Rhubarbあなたは完全に正しいです。私の答えでそれを指摘します。ありがとう。
ロレンゾB

回答が得られるかどうかはわかりませんが、境界の原点が変更されると、サブビューが負の方向に移動するのはなぜですか。ちょっと頭が動かないようです。ありがとう!!
nimgrg 2013年

@nimgrgビューは負の方向に動いているようですが、そうではありません。スーパービューの内部座標が変更されました。
Lorenzo B

スーパービューの内部座標が原点(30.0、20.0)に変更された場合、幾何学的能力を許して、ポイント(0,0)は青い正方形の内側または外側にあります。私は変更を追跡し、それを理解しようとしています。回答していただきありがとうございます。
nimgrg 2013年

@flexaddicted:こんにちは、追加したスライドでは、「ビューBの独自の座標空間での中央は次のとおりです:bounds.size.width / 2 + origin.x」-これはなぜですか?タイトルはそれ自身の座標空間で言うので、私はそれを次のように言うでしょう:bounds.size.width / 2 + bounds.origin.x ?? じゃないですか?

134

この質問にはすでに良い答えがありますが、もう少し写真で補足したいと思います。 私の完全な答えはここにあります。

私が覚えて支援するためのフレームを、私は考える壁に額縁。写真が壁のどこにでも移動できるように、ビューのフレームの座標系はスーパービューです。(壁=スーパービュー、フレーム=ビュー)

境界を思い出しやすくするために、バスケットボールコートの境界を思い浮かべます。バスケットボールは、ビューの境界の座標系がビュー自体の中にあるのと同じように、コート内のどこかにあります。(court = view、バスケットボール/ players = view内のコンテンツ)

フレームのように、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

ここに画像の説明を入力してください

繰り返しますが、詳細については私の回答はこちらをご覧ください。


2
Suragchに感謝します。フレームと境界の違いが本当に非常にはっきりしています。本当にありがとうございました。
Mohd Haider 2015年

私が見たいすべてのものを1つの短く簡潔な答えで。ありがとう!
Matt Chuang

驚くばかり!例3:わかりません。フレームの原点を少しだけ移動しただけで、画像の回転がどのように変化しますか?
ハニー

@ asma22、例3では、画像を回転させたときにフレームは変更されますが、境界は変更されないことを示しているだけです。私の完全な答えを見てください
Suragch

89

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

ここに画像の説明を入力してください

frame.size != bounds.size画像が回転している場合もご注意ください。


14
千の言葉に値する絵。
Narendra Kamma、2012年

3
考えられる最良の説明
Ratikanta Patra 2013

@Erben Mo:こんにちは、追加したスライドは次のように述べています。タイトルはそれ自身の座標空間で言うので、私はそれを次のように言うでしょう:bounds.size.width / 2 + bounds.origin.x ?? じゃないですか?

1
この画像の出所は何ですか?リンク?
デビッド

1
@Davidこれは、スタンフォードのiTunesUのCS193pコースからのものです。www.stanford.edu/ class
cs193p

3

の観点から考えればCALayer、すべてがもっとはっきりしていると思います。

フレームは、実際にはビューまたはレイヤーの個別のプロパティではなく、境界、position(UIViewの中心)、および変換です。

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



0

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

オンラインでブラウジングするとします。Webブラウザは、Webframeページを表示する場所と大きさを決定するあなたのものです。ブラウザのスクローラーはあなた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));
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.