固有のコンテンツサイズのビュー
次のレシピは、固有のコンテンツサイズを持つビューの操作を示します。一般に、固有のコンテンツサイズはレイアウトを簡素化し、必要な制約の数を減らします。ただし、固有のコンテンツサイズを使用するには、多くの場合、ビューのコンテンツハグと圧縮耐性 (CHCR) の優先順位を設定する必要があり、さらに複雑になる可能性があります。
これらのレシピのソースコードを表示するには、 Auto Layout Cookbook プロジェクトを参照してください。
簡単なラベルとテキストフィールド
このレシピは、簡単なラベルとテキストフィールドのペアのレイアウトを示します。この例では、ラベルの幅はそのテキストプロパティのサイズに基づいており、テキストフィールドは残りのスペースに合わせて拡大・縮小します。
このレシピはビュー固有のコンテンツサイズを使用するため、レイアウトを一意に指定するために必要な制約は 5 つだけです。ただし、正しいサイズ変更動作を得るには、CHCR の優先順位が正しいことを確認する必要があります。
固有のコンテンツサイズと CHCR の優先順位の詳細については、固有のコンテンツサイズ を参照してください。
ビューと制約
Interface Builder で、ラベルとテキストフィールドをドラッグアウトします。ラベルのテキストとテキストフィールドのプレースホルダーを設定し、図のように制約を設定します。
- Name Label.Leading = Superview.LeadingMargin
- Name Text Field.Trailing = Superview.TrailingMargin
- Name Text Field.Leading = Name Label.Trailing + Standard
- Name Text Field.Top = Top Layout Guide.Bottom + 20.0
- Name label.Baseline = Name Text Field.Baseline
属性
利用可能なスペースを満たすようにテキストフィールドを伸ばすには、コンテンツのハグがラベルのハグよりも低くなければなりません。デフォルトでは、Interface Builder はラベルのコンテンツハグを 251 に、テキストフィールドを 250 に設定する必要があります。これはサイズインスペクタで確認できます。
名前 | 横抱き (Horizontal hugging) | 垂直抱き | 水平抵抗 | 垂直抵抗 |
名前ラベル | 251 | 251 | 750 | 750 |
名前のテキストフィールド | 250 | 250 | 750 | 750 |
議論
このレイアウトは、垂直レイアウトを定義するために 2 つの制約 (4 および 5) のみを使用し、水平レイアウトを定義するために 3 つの制約 (1、2、および 3) のみを使用していることに注意してください。明確で満足できるレイアウトの作成 の経験則によれば、ビューごとに 2 つの水平制約と 2 つの垂直制約が必要です。ただし、ラベルとテキストフィールドの固有のコンテンツサイズは、高さとラベルの幅を提供するため、3 つの制約が不要になります。
このレイアウトはまた、テキストフィールドが常にラベルテキストよりも高いという単純化された仮定も行い、テキストフィールドの高さを使用して上端のレイアウトガイドからの距離を定義します。ラベルとテキストフィールドの両方がテキストの表示に使用されるため、レシピはテキストのベースラインを使用してそれらを整列します。
水平方向では、利用可能なサイズを満たすためにどのビューが拡大すべきか定義する必要があります。これを行うには、ビューの CHCR の優先順位を変更します。この例では、Interface Builder はすでに名前ラベルの水平および垂直抱きの優先順位を 251 に設定しているはずです。これはテキストフィールドのデフォルトの 250 よりも大きいため、テキストフィールドは追加のスペースを埋めるために拡大されます。
コントロールに対して小さすぎるスペースにレイアウトが表示される場合は、圧縮抵抗の値も変更する必要があります。圧縮抵抗は、十分なスペースがないときにどのビューを切り捨てるべきかを定義します。
この例では、圧縮抵抗を変更することは、読者のための演習として残されています。名前ラベルのテキストまたはフォントが十分に大きい場合、ただし、十分なスペースがない場合、あいまいなレイアウトになります。次に、システムは違反する制約を選択し、テキストフィールドまたはラベルのいずれかが切り捨てられます。
理想的には、必要に応じてコンパクトサイズクラスの代替レイアウトを使用して、利用可能なスペースに対して決して大きすぎないレイアウトを作成する必要があります。ただし、複数の言語と動的な型をサポートするビューを設計する場合、行がどのくらい大きくなるかを正確に予測することは困難です。万が一に備えて、圧縮抵抗を変更することは、安全弁として適切です。
動的高さラベルとテキストフィールド
簡単なラベルとテキストフィールド のレシピでは、テキストフィールドは常に名前ラベルよりも高くなると想定して、レイアウトの論理を簡略化しました。ただし、これは必ずしも常に正しいとは限りません。ラベルのフォントサイズを十分に大きくすると、テキストフィールドの上に拡大されます。
このレシピは、実行時に最も高いコントロールに基づいて、コントロールの垂直方向の間隔を動的に設定します。通常のシステムフォントでは、このレシピは 簡単なラベルとテキストフィールド のレシピと同一なように見えます (スクリーンショットを参照)。ただし、ラベルのフォントサイズを 36.0 ポイントに増やすと、レイアウトの垂直方向の間隔は代わりにラベルの上端から計算されます。
これはやや不自然な例です。結局のところ、ラベルのフォントサイズを大きくすると、通常はテキストフィールドのフォントサイズも大きくなります。ただし、iPhone のアクセシビリティ設定を介して利用できる大きな、大きな、非常に大きなフォントがある場合、この手法は、動的な型と固定サイズのコントロール (画像など) を混在させる場合に役立ちます。
ビューと制約
簡単なラベルとテキストフィールド で行ったようにビュー階層を設定しますが、やや複雑な一連の制約を使用します。
- Name Label.Leading = Superview.LeadingMargin
- Name Text Field.Trailing = Superview.TrailingMargin
- Name Text Field.Leading = Name Label.Trailing + Standard
- Name Label.Top >= Top Layout Guide.Bottom + 20.0
- Name Label.Top = Top Layout Guide.Bottom + 20.0 (Priority 249)
- Name Text Field.Top >= Top Layout Guide.Bottom + 20.0
- Name Text Field.Top = Top Layout Guide.Bottom + 20.0 (Priority 249)
- Name label.Baseline = Name Text Field.Baseline
属性
利用可能なスペースを満たすようにテキストフィールドを拡大するには、コンテンツのハグがラベルのハグよりも低くなければなりません。デフォルトでは、Interface Builder はラベルのコンテンツハグを 251 に、テキストフィールドを 250 に設定する必要があります。これはサイズインスペクタで確認できます。
名前 | 横抱き (Horizontal hugging) | 垂直抱き | 水平抵抗 | 垂直抵抗 |
名前ラベル | 251 | 251 | 750 | 750 |
名前のテキストフィールド | 250 | 250 | 750 | 750 |
議論
このレシピでは、各コントロールに一対の制約を使用しています。オプションの制約は、コントロールをレイアウトガイドから正確に 20.0 ポイントに引っ張ろうとしますが、必須の "以上" の制約は、そのコントロールとレイアウトガイドの間の最小距離を定義します。
どちらの制約も背の高い制約を満たすので、システムはレイアウトガイドから正確に 20.0 ポイントにそれを配置します。ただし、より短い制御では、最小距離のみが満足できます。他の制約は無視されます。これにより、実行時にコントロールの高さが変化すると、自動レイアウトシステムが動的にレイアウトを再計算します。
オプションの制約の優先度は、デフォルトのコンテンツハグ制約 (250) よりも低い値に設定してください。それ以外の場合、システムはコンテンツハグの制約を破り、ビューを再配置する代わりにビューを引き伸ばします。
これは、ベースライン配置を使用するレイアウトで作業する場合に特に混乱する可能性があります。ベースライン配置は、テキストビューが固有のコンテンツの高さで表示される場合にのみ有効であるためです。システムがいずれかのビューのサイズを変更すると、必要なベースライン制約があるにもかかわらず、テキストは適切に整列しない場合があります。
固定された高さの列
このレシピは、簡単なラベルとテキストフィールド のレシピをラベルとテキストフィールドの列に拡張します。ここでは、すべてのラベルの後端が整列されています。テキストフィールドの先端と後端が整列され、水平方向の配置は最長のラベルに基づきます。ただし、簡単なラベルとテキストフィールドのレシピと同様に、このレシピはテキストフィールドが常にラベルよりも高いと想定することで、レイアウトの論理を簡素化しています。
ビューと制約
ラベルとテキストフィールドをレイアウトし、図のように制約を設定します。
- First Name Label.Leading = Superview.LeadingMargin
- Middle Name Label.Leading = Superview.LeadingMargin
- Last Name Label.Leading = Superview.LeadingMargin
- First Name Text Field.Leading = First Name Label.Trailing + Standard
- Middle Name Text Field.Leading = Middle Name Label.Trailing + Standard
- Last Name Text Field.Leading = Last Name Label.Trailing + Standard
- First Name Text Field.Trailing = Superview.TrailingMargin
- Middle Name Text Field.Trailing = Superview.TrailingMargin
- Last Name Text Field.Trailing = Superview.TrailingMargin
- First Name Label.Baseline = First Name Text Field.Baseline
- Middle Name Label.Baseline = Middle Name Text Field.Baseline
- Last Name Label.Baseline = Last Name Text Field.Baseline
- First Name Text Field.Width = Middle Name Text Field.Width
- First Name Text Field.Width = Last Name Text Field.Width
- First Name Text Field.Top = Top Layout Guide.Bottom + 20.0
- Middle Name Text Field.Top = First Name Text Field.Bottom + Standard
- Last Name Text Field.Top = Middle Name Text Field.Bottom + Standard
属性
属性インスペクタで、以下の属性を設定します。特に、すべてのラベルのテキストを右に整列します。これにより、テキストよりも長いラベルを使用しながら、テキストフィールドの横の端を整列することができます。
ビュー | 属性 | 値 |
ファーストネームのラベル | テキスト | ファーストネーム |
ファーストネームのラベル | 整列 | 右 |
ファーストネームのテキストフィールド | プレースホルダ | ファーストネームの入力 |
ミドルネームのラベル | テキスト | ミドルネーム |
ミドルネームのラベル | 整列 | 右 |
ミドルネームのテキストフィールド | プレースホルダ | ミドルネームの入力 |
ラストネームのラベル | /テキスト | ラストネーム |
ラストネームのラベル | 整列 | 右 |
ラストネームのテキストフィールド | プレースホルダ | ラストネームの入力 |
各ペアごとに、ラベルのコンテンツハグはテキストフィールドよりも高くしなければなりません。この場合も、Interface Builder はこれを自動的に行う必要があります。ただし、これらの優先度はサイズインスペクタで確認できます。
名前 | 水平ハグ | 垂直ハグ | 水平抵抗 | 垂直抵抗 |
ファーストネームのラベル | 251 | 251 | 750 | 750 |
ファーストネームのテキストフィールド | 250 | 250 | 750 | 750 |
ミドルネームのラベル | 251 | 251 | 750 | 750 |
ミドルネームのテキストフィールド | 250 | 250 | 750 | 750 |
ラストネームのラベル | 251 | 251 | 750 | 750 |
ラストネームのテキストフィールド | 250 | 250 | 750 | 750 |
議論
このレシピは基本的に、簡単なラベルとテキストフィールド のレイアウトの 3 つのコピーから始まり、一つを他のスタックの上に重ねたものです。ただし、行が正しく並ぶようにいくつか追加する必要があります。
まず、各ラベルのテキストを右揃えにして問題を単純化します。これで、すべてのラベルを同じ幅にすることができ、テキストの長さに関係なく、ラベルの後端を簡単に揃えることができます。さらに、ラベルの耐圧縮性はコンテンツハグよりも大きいため、すべてのラベルは圧搾されるよりも引き伸ばされることを選びます。先端と後端を揃えると、ラベルはすべて、最も長いラベル固有のコンテンツサイズまで自然に伸びます。
したがって、すべてのラベルの先端と後端を揃える必要があります。また、すべてのテキストフィールドの先端と後端を揃える必要があります。幸い、ラベルの先端はすでにスーパービューの先端マージンに揃えられています。同様に、テキストフィールドの後端はすべて、スーパービューの後端マージンに揃えられます。他の 2 つの端の 1 つを揃えるだけで、すべての行が同じ幅になるため、すべてが揃います。
これを行うにはいくつもの方法があります。このレシピでは、各テキストフィールドに同じ幅を与えます。
動的な高さの列
このレシピは、動的高さラベルとテキストフィールド レシピと 固定された高さの列 のレシピで学習したすべてを組み合わせたものです。このレシピの目標は以下のとおりです。
- 最長のラベルの長さに基づいて、ラベルの後端が揃えられます。
- テキストフィールドの幅は同じで、先端と後端が揃っています。
- テキストフィールドが展開され、スーパービューの残りのスペースがすべて満たされます。
- 行間の高さは、行の最も高い要素に基づいています。
- すべてが動的であるため、フォントサイズやラベルテキストが変更されると、レイアウトは自動的に更新されます。
ビューと制約
固定された高さの列で行ったように、ラベルとテキストフィールドをレイアウトします。ただし、いくつかの追加の制約が必要です。
- First Name Label.Leading = Superview.LeadingMargin
- Middle Name Label.Leading = Superview.LeadingMargin
- Last Name Label.Leading = Superview.LeadingMargin
- First Name Text Field.Leading = First Name Label.Trailing + Standard
- Middle Name Text Field.Leading = Middle Name Label.Trailing + Standard
- Last Name Text Field.Leading = Last Name Label.Trailing + Standard
- First Name Text Field.Trailing = Superview.TrailingMargin
- Middle Name Text Field.Trailing = Superview.TrailingMargin
- Last Name Text Field.Trailing = Superview.TrailingMargin
- First Name Label.Baseline = First Name Text Field.Baseline
- Middle Name Label.Baseline = Middle Name Text Field.Baseline
- Last Name Label.Baseline = Last Name Text Field.Baseline
- First Name Text Field.Width = Middle Name Text Field.Width
- First Name Text Field.Width = Last Name Text Field.Width
- First Name Label.Top >= Top Layout Guide.Bottom + 20.0
- First Name Label.Top = Top Layout Guide.Bottom + 20.0 (Priority 249)
- First Name Text Field.Top >= Top Layout Guide.Bottom + 20.0
- First Name Text Field.Top = Top Layout Guide.Bottom + 20.0 (Priority 249)
- Middle Name Label.Top >= First Name Label.Bottom + Standard
- Middle Name Label.Top = First Name Label.Bottom + Standard (Priority 249)
- Middle Name Text Field.Top >= First Name Text Field.Bottom + Standard
- Middle Name Text Field.Top = First Name Text Field.Bottom + Standard (Priority 249)
- Last Name Label.Top >= Middle Name Label.Bottom + Standard
- Last Name Label.Top = Middle Name Label.Bottom + Standard (Priority 249)
- Last Name Text Field.Top >= Middle Name Text Field.Bottom + Standard
- Last Name Text Field.Top = Middle Name Text Field.Bottom + Standard (Priority 249)
属性
属性インスペクタで、以下の属性を設定します。特に、すべてのラベルのテキストを右揃えにします。ラベルを右揃えにすると、テキストよりも長いラベルを使用でき、テキストの端がテキストフィールドの横に揃います。
ビュー | 属性 | 値 |
ファーストネームのラベル | テキスト | ファーストネーム |
ファーストネームのラベル | 整列 | 右 |
ファーストネームのテキストフィールド | プレースホルダ | ファーストネームを入力 |
ミドルネームのラベル | テキスト | ミドルネーム |
ミドルネームのラベル | 整列 | 右 |
ミドルネームのテキストフィールド | プレースホルダ | ミドルネームを入力 |
ラストネームのラベル | テキスト | ラストネーム |
ラストネームのラベル | 整列 | 右 |
ラストネームのテキストフィールド | プレースホルダ | ラストネームを入力 |
各ペアごとに、ラベルのコンテンツハグはテキストフィールドよりも高くしなければなりません。この場合も、Interface Builder はこれを自動的に行います。ただし、これらの優先順位はサイズインスペクタで確認できます。
名前 | 水平ハグ | 垂直ハグ | 水平抵抗 | 垂直抵抗 |
ファーストネームのラベル | 251 | 251 | 750 | 750 |
ファーストネームのテキストフィールド | 250 | 250 | 750 | 750 |
ミドルネームのラベル | 251 | 251 | 750 | 750 |
ミドルネームのテキストフィールド | 250 | 250 | 750 | 750 |
ラストネームのラベル | 251 | 251 | 750 | 750 |
ラストネームのテキストフィールド | 250 | 250 | 750 | 750 |
議論
このレシピは、動的高さラベルとテキストフィールド および 固定された高さの列 のレシピで説明されている手法を単に組み合わせたものです。動的高さラベルとテキストフィールドのレシピと同様に、このレシピは制約のペアを使用して、行間の垂直間隔を動的に設定します。固定された高さの列のレシピと同様に、ラベルで右揃えのテキストを使用し、列を整列させるために明示的な等しい幅の制約を使用します。
この例では、ビューと上端のレイアウトガイド間の距離に 20.0 ポイントの間隔を使用し、兄弟のビュー間に 8.0 の間隔を使用しています。これにより、20 ポイントの固定された上端マージンを設定する効果があります。バーの有無に応じて自動的に調整されるマージンが必要な場合は、さらに制約を追加しなければなりません。一般的な手法は、適応するシングルビュー のレシピに示されています。ただし、正確な実装は読者の課題として残されています。
ご覧のとおり、レイアウトの論理はやや複雑になり始めています。ただし、物事を簡略化する方法はいくつかあります。まず、前述のように、可能な限りスタックビューを使用する必要があります。または、コントロールをグループ化してから、グループをレイアウトすることもできます。これにより、単一の複雑なレイアウトを、より小さく管理しやすい塊に分割できます。
2 つの幅の等しいボタン
このレシピは、2 つの等しいサイズのボタンのレイアウトを示しています。垂直方向に、ボタンはクリーンの下端に配置されます。水平方向に、利用可能なすべてのスペースを満たすようにそれらは引き伸ばされます。
ビューと制約
Interface Builder で、2 つのボタンをシーンにドラッグします。シーンの下端に沿ったガイドラインを使用してそれらを整列します。ボタンを同じ幅にする必要はありません。ボタンの 1 つを引き伸ばして、残りの水平スペースを満たしてください。おおまかに配置したら、以下の制約を設定します。自動レイアウトは、正しい最終的な位置を計算します。
- Short Button.Leading = Superview.LeadingMargin
- Long Button.Leading = Short Button.Trailing + Standard
- Long Button.Trailing = Superview.TrailingMargin
- Bottom Layout Guide.Top = Short Button.Bottom + 20.0
- Bottom Layout Guide.Top = Long Button.Botton + 20.0
- Short Button.Width = Long Button.Width
属性
デバイスの回転に応じてボタンのフレームがどのように変化するかを簡単に確認できるように、ボタンに背景色を与えます。さらに、ボタンに異なる長さのタイトルを使用して、ボタンのタイトルがボタンの幅に影響しないことを示します。
ビュー | 属性 | 値 |
短いボタン | 背景 | 薄い灰色 |
短いボタン | タイトル | 短い |
長いボタン | 背景 | 薄い灰色 |
長いボタン | タイトル | とても長いボタンのタイトル |
議論
このレシピでは、レイアウトの計算時にボタンの固有の高さを使用しますが、幅は使用しません。水平方向では、ボタンは明示的にサイズが調整されているため、ボタンの幅は等しく、使用可能なスペースを満たします。ボタンの固有の高さがレイアウトにどのように影響するかを確認するには、このレシピを 2 つの等幅ビュー のレシピと比較してください。このレシピでは、4 つではなく 2 つの垂直制約しかありません。
ボタンにはまた、非常に異なる長さのタイトルが付けられており、ボタンのテキストがレイアウトにどのように影響する (またはこの場合は影響しない) かを示します。
このレシピでは、ボタンに薄い灰色の背景色が与えられ、ボタンのフレームが表示されます。通常、ボタンとラベルの背景は透明であるため、フレームの変更を確認することは (不可能ではないにしても) 困難です。
3 つの幅の等しいボタン
このレシピは、2 つの幅の等しいボタン のレシピを拡張して、3 つの幅の等しいボタンを使用するようにします。
ビューと制約
ボタンをレイアウトし、図のように制約を設定します。
- Short Button.Leading = Superview.LeadingMargin
- Medium Button.Leading = Short Button.Trailing + Standard
- Long Button.Leading = Medium Button.Trailing + Standard
- Long Button.Trailing = Superview.TrailingMargin
- Bottom Layout Guide.Top = Short Button.Bottom + 20.0
- Bottom Layout Guide.Top = Medium Button.Bottom + 20.0
- Bottom Layout Guide.Top = Long Button.Bottom + 20.0
- Short Button.Width = Medium Button.Width
- Short Button.Width = Long Button.Width
属性
デバイスの回転に応じてボタンのフレームがどのように変化するかを簡単に確認できるように、ボタンに見える背景色を与えます。さらに、ボタンに異なる長さのタイトルを使用して、ボタンのタイトルがボタンの幅に影響しないことを示します。
パラ | ビュー | 属性 | 値 |
短いボタン | 背景 | 薄い灰色 | |
短いボタン | タイトル | 短い | |
中間のボタン | 背景 | 薄い灰色 | |
中間のボタン | タイトル | 中間の | |
長いボタン | 背景 | 薄い灰色 | |
長いボタン | タイトル | 長いボタンのタイトル |
議論
余分のボタンを追加するには、3 つの余分の制約 (2 つの水平制約と 1 つの垂直制約) を追加する必要があります。ボタン固有の幅を使用していないため、位置とサイズの両方を一意に指定するには、少なくとも 2 つの水平方向の制約が必要です。ただし、ボタン固有の高さを使用しているため、垂直位置を指定するために必要な追加の制約は 1 つだけです。
幅の等しい制約をすばやく設定するには、3 つのボタンすべてを選択してから、Interface Builder の固定 (Pin) ツールを使用して幅の等しい制約を作成します。Interface Builder は必要な制約を両方とも自動的に作成します。
間隔の等しい 2 つのボタン
表面的には、このレシピは 2 つの幅の等しいボタン のレシピに似ています (スクリーンショットを参照)。ただし、このレシピでは、ボタンの幅は最も長いタイトルに基づいています。十分なスペースがある場合、ボタンは、両方が長いボタン固有のコンテンツサイズに一致するまでのみ引き伸ばされます。追加のスペースはボタンの周りに均等に分割されます。
iPhone 上では、2 つの幅の等しいボタンと 2 つの間隔の等しいボタンのレイアウトは、縦向き (portrait) ではほぼ同一に表示されます。この違いは、デバイスを横向き (landscape) に回転させた場合 (または iPad などの大きなデバイスを使用した場合) にのみ明らかになります。
ビューと制約
Interface Builder で、2 つのボタンと 3 つのビューオブジェクトをドラッグして配置します。ビューの間にボタンを配置し、次に制約を図のように設定します。
- Leading Dummy View.Leading = Superview.LeadingMargin
- Short Button.Leading = Leading Dummy View.Trailing
- Center Dummy View.Leading = Short Button.Trailing
- Long Button.Leading = Center Dummy View.Trailing
- Trailing Dummy View.Leading = Long Button.Trailing
- Trailing Dummy View.Trailing = Superview.TrailingMargin
- Bottom Layout Guide.Top = Leading Dummy View.Bottom + 20.0
- Bottom Layout Guide.Top = Short Button.Bottom + 20.0
- Bottom Layout Guide.Top = Center Dummy View.Bottom + 20.0
- Bottom Layout Guide.Top = Long Button.Bottom + 20.0
- Bottom Layout Guide.Top = Trailing Dummy View.Bottom + 20.0
- Short Button.Leading >= Superview.LeadingMargin
- Long Button.Leading >= Short Button.Trailing + Standard
- Superview.TrailingMargin >= Long Button.Trailing
- Leading Dummy View.Width = Center Dummy View.Width
- Leading Dummy View.Width = Trailing Dummy View.Width
- Short Button.Width = Long Button.Width
- Leading Dummy View.Height = 0.0
- Center Dummy View.Height = 0.0
- Trailing Dummy View.Height = 0.0
属性
デバイスの回転に応じてボタンのフレームがどのように変化するかを簡単に確認できるように、ボタンに見える背景色を与えます。さらに、ボタンには異なる長さのタイトルを使用します。ボタンは、最も長いタイトルに基づいてサイズを調整します。
ビュー | 属性 | 値 |
短いボタン | 背景 | 薄い灰色 |
短いボタン | タイトル | 短い |
長いボタン | 背景 | 薄い灰色 |
長いボタン | タイトル | 更に長いボタンのタイトル |
議論
ご覧のように、一連の制約は複雑になっています。この例は特定の手法を示すために設計されていますが、実際のアプリでは、代わりにスタックビューの使用を検討する必要があります。
この例では、スーパービューのフレームが変わると、空白のサイズが変わるようにしたいですね。つまり、空白の幅を制御するには、等しい幅の制約のセットが必要です。ただし、空のスペースに制約を作成することはできません。サイズを制限できる何らかのオブジェクトがなければなりません。
このレシピでは、空のスペースを表すためにダミーのビューを使用します。これらのビューは、UIView クラスの空のインスタンスです。このレシピでは、ビュー階層への影響を最小限に抑えるために、0 ポイントの高さが与えられています。
ダミービューはレイアウトにかなりのコストを追加する可能性があるため、慎重に使用する必要があります。これらのビューが大きい場合、意味のある情報が含まれていなくても、グラフィックコンテキストはかなりの量のメモリを消費する可能性があります。
さらに、これらのビューはビュー階層のレスポンダーチェーンに参加します。これは、ヒットテストなど、レスポンダーチェーンに沿って送信されるメッセージに応答することを意味します。注意深く処理されない場合、これらのビューはこれらのメッセージを傍受して応答し、見つけにくいバグを作成する可能性があります。
または、UILayoutGuide クラスのインスタンスを使用して、空白を表すこともできます。この軽量クラスは、自動レイアウト制約に参加できる長方形のフレームを表します。レイアウトガイドにはグラフィックコンテキストがなく、またビュー階層の一部でもありません。このため、レイアウトガイドは、項目のグループ化や空白の定義に理想的です。
残念ながら、Interface Builder でシーンにレイアウトガイドを追加することはできません。また、プログラムで作成されたオブジェクトをストーリーボードベースのシーンと混合すると、非常に複雑になる可能性があります。一般的な経験則として、カスタムレイアウトガイドを使用するよりも、ストーリーボードと Interface Builder を使用する方が適切です。
このレシピでは、ボタンの周囲の最小間隔を設定するために、"以上" の制約を使用しています。必要な制約もまた、ボタンが常に同じ幅であり、ダミービューも常に同じ幅であることが保証されます (ただし、ボタンとは異なる幅にすることもできます)。残りのレイアウトは、主にボタンの CHCR 優先度によって管理されます。十分なスペースがない場合、ダミービューは 0 ポイントの幅に折りたたまれ、ボタンは使用可能なスペースをそれら自身の間で (標準の間隔で) 分割します。使用可能なスペースが増えると、ボタンはより大きなボタン固有の幅に達するまで拡大し、その後ダミービューが拡大し始めます。ダミービューは、残りのスペースを埋めるために拡大し続けます。
2 つのボタンとサイズクラスベースのレイアウト
このレシピでは、2 つの異なる制約のセットを使用します。1 つは Any-Any レイアウト用にインストールされます。これらの制約は、2 つの幅の等しいボタン のレシピと同一の、一対の等幅ボタンを定義します。
その他の制約のセットは、Compact-Regular レイアウト上にインストールされます。これらの制約は、以下に示すように、一対のスタックボタンを定義します。
垂直なスタックボタンは、縦向き (portrait) で iPhone で使用されます。ボタンの水平の行は、他の場所でも使用されます。
制約
2 つの幅の等しいボタンのレシピでまさに行ったとおりにボタンをレイアウトします。Any-Any サイズクラスで、制約 1〜6 を設定します。
次に、Interface Builder のサイズクラスを Compact-Regular レイアウトに切り替えます。
図のように、制約 2 と制約 5 をアンインストールし、制約 7、8、9 を追加します。
- Short Button.Leading = Superview.LeadingMargin
- Long Button.Leading = Short Button.Trailing + Standard
- Long Button.Trailing = Superview.TrailingMargin
- Bottom Layout Guide.Top = Short Button.Bottom + 20.0
- Bottom Layout Guide.Top = Long Button.Botton + 20.0
- Short Button.Width = Long Button.Width
- Long Button.Leading = Superview.LeadingMargin
- Short Button.Trailing = Superview.TrailingMargin
- Long Button.Top = Short Button.Bottom + Standard
属性
デバイスの回転に応じてボタンのフレームがどのように変化するかを簡単に確認できるように、ボタンに見える背景色を与えます。さらに、ボタンに異なる長さのタイトルを使用して、ボタンのタイトルがボタンの幅に影響しないことを示します。
ビュー | 属性 | 値 |
短いボタン | 背景 | 薄い灰色 |
短いボタン | タイトル | 短い |
長いボタン | 背景 | 薄い灰色 |
長いボタン | タイトル | とても長いボタンのタイトル |
議論
Interface Builder を使用すると、サイズクラス固有のビュー、ビュー属性、および制約を設定できます。幅と高さの両方に 3 つの異なるサイズクラス (コンパクト、Any、または標準) の異なるオプションを指定して、合計 9 つの異なるサイズクラスを指定できます。それらの 4 つは、デバイスで使用される最終サイズクラスに対応します (コンパクト-コンパクト、コンパクト-標準、標準-コンパクト、および標準-標準)。 残りは、ベースサイズクラス、または 2 つ以上のサイズクラスの抽象表現 (コンパクト-Any、標準-Any、Any-コンパクト、Any-標準、および Any-Any) です。
与えられたサイズクラスのレイアウトをロードすると、システムはそのサイズクラスの最も具体的な設定をロードします。つまり、Any-Any サイズクラスは、すべてのビューで使用されるデフォルト値を定義する事を意味します。コンパクト-Any の設定は、コンパクトな幅のすべてのビューに影響します。コンパクト-標準設定は、コンパクトな幅と標準の高さのビューにのみ使用されます。ビューのサイズクラスが変更されると、たとえば、iPhone が縦向き (portrait) から横向き (landscape) に回転すると、システムは自動的にレイアウトを交換し、変更をアニメーション化します。
この機能を使用して、さまざまな iPhone の向きに合わせて異なるレイアウトを作成できます。これを使用して、iPad と iPhone の異なるレイアウトを作成することもできます。サイズクラス固有のカスタマイズは、必要に応じて幅広くすることも、単純にすることもできます。もちろん、変更が多ければ多いほど、ストーリーボードは複雑になり、設計と保守が難しくなります。
すべての基本サイズクラスを含め、可能な各サイズクラスに有効なレイアウトがあることを確認する必要があることに注意してください。一般的なルールとして、デフォルトのレイアウトとして 1 つのレイアウトを選択するのが通常最も簡単です。Any-Any サイズクラスでそのレイアウトを設計します。次に、必要に応じて最終サイズのクラスを変更します。より具体的なサイズクラス内の項目は、追加と削除の両方が可能な事に注意して下さい。
より複雑なレイアウトの場合は、開始する前に、サイズクラスの 9 x 9 グリッドを描画することができます。これらのサイズクラスのレイアウトを四隅に記入します。そしてグリッドを使用すると、複数のサイズクラスで共有されている制約を確認でき、レイアウトとサイズクラスの最適な組み合わせを見つけることができます。
サイズクラスの操作の詳細については、自動レイアウトのデバッグ を参照してください。
前:簡単な制約 次:エラーの型