制約の構造


ビュー階層のレイアウトは、一連の線形方程式として定義されます。各制約は 1 つの方程式を表します。あなたの目標は、可能な解が 1 つだけある一連の方程式を宣言することです。


方程式の例を以下に示します。


view_formula_2x


この制約は、赤いビューの先端は、青いビューの後端の後 8.0 ポイントでなければならないことを示しています。その方程式にはいくつかの部分があります。


ほとんどの制約は、ユーザインターフェイスの 2 つの項目間の間の関係を定義します。これらの項目は、ビューまたはレイアウトガイドを表します。制約はまた、単一の項目の 2 つの異なる属性間の関係を定義することもできます。たとえば、項目の高さと幅の間のアスペクト比を設定します。項目の高さまたは幅に定数値を割り当てることもできます。定数値を使用する場合、2 番目の項目は空白のままになり、2 番目の属性は "属性なし (Not An Attribute)" に設定され、乗数は 0.0 に設定されます。


自動レイアウト属性


自動レイアウトでは、属性は制約可能な機能を定義します。一般に、これには 4 つの端 (先端、後端、上端、底端) と、高さ、幅、および垂直方向と水平方向の中心が含まれます。テキストの項目には、1 つ以上のベースライン属性もあります。


attributes_2x


属性の完全なリストについては、NSLayoutAttribute 列挙型を参照してください。


注意:

OS X と iOS はどちらも NSLayoutAttribute 列挙型を使用しますが、わずかに異なる値のセットを定義します。属性の完全なリストを表示するには、正しいプラットフォームのドキュメントを参照していることを確認してください。




方程式の例


これらの方程式で使用できる幅広いパラメータと属性により、さまざまな型の制約を作成できます。ビューの間のスペースを定義したり、ビューの端を揃えたり、2 つのビューの相対的なサイズを定義したり、ビューのアスペクト比を定義したりすることもできます。ただし、すべての属性に互換性があるわけではありません。


属性には 2 つの基本的な型があります。サイズ属性 (例えば、高さと幅など) と位置属性 (例えば、行送り、左、上など) 。サイズ属性は、項目の場所を示すことなく、項目の大きさを指定するために使用されます。位置属性は、他のものに対する項目の位置を指定するために使用されます。ただし、項目のサイズは表示されません。


これらの違いを考慮して、以下のルールが適用されます。


たとえば、項目の上端を定数値 20.0 に設定しても、追加のコンテキストがないと意味がありません。常に、他の項目との関連で項目の位置属性を定義しなければなりません。たとえば、スーパービューの上端の下 20.0 ポイント。ただし、項目の高さを 20.0 に設定しても完全に有効です。詳細については、値の解釈 を参照してください。


リスト 3-1 は、さまざまな一般的な制約の方程式の例を示しています。


注意:

この章のすべての方程式の例は、疑似コードを使用して示されています。実際のコードを使用して実際の制約を確認するには、プログラムによる制約の作成 または 自動レイアウトレシピ集 を参照してください。




リスト 3-1 一般的な制約の方程式の例


 1    // Setting a constant height
 2    View.height = 0.0 * NotAnAttribute + 40.0
 3     
 4    // Setting a fixed distance between two buttons
 5    Button_2.leading = 1.0 * Button_1.trailing + 8.0
 6     
 7    // Aligning the leading edge of two buttons
 8    Button_1.leading = 1.0 * Button_2.leading + 0.0
 9     
10    // Give two buttons the same width
11    Button_1.width = 1.0 * Button_2.width + 0.0
12     
13    // Center a view in its superview
14    View.centerX = 1.0 * Superview.centerX + 0.0
15    View.centerY = 1.0 * Superview.centerY + 0.0
16     
17    // Give a view a constant aspect ratio
18    View.height = 2.0 * View.width + 0.0


代入ではなく等式


注意 に示されている方程式は代入ではなく等式を表していることに注意することが重要です。


自動レイアウトがこれらの方程式を解くとき、右辺の値を左辺に代入するだけではありません。代わりに、関係を真にする属性 1 と属性 2 の両方の値を計算します。これは、方程式の項目を自由に並べ替えることができることを意味します。たとえば、リスト 3-2 の方程式は、注意 の対応する方程式と全く同じです。


リスト 3-2 逆方程式


 1    // Setting a fixed distance between two buttons
 2    Button_1.trailing = 1.0 * Button_2.leading - 8.0
 3     
 4    // Aligning the leading edge of two buttons
 5    Button_2.leading = 1.0 * Button_1.leading + 0.0
 6     
 7    // Give two buttons the same width
 8    Button_2.width = 1.0 * Button.width + 0.0
 9     
10    // Center a view in its superview
11    Superview.centerX = 1.0 * View.centerX + 0.0
12    Superview.centerY = 1.0 * View.centerY + 0.0
13     
14    // Give a view a constant aspect ratio
15    View.width = 0.5 * View.height + 0.0


注意:

項目を並べ替えるときは、乗数と定数を反転させてください。たとえば、定数 8.0-8.0 になります。2.0 の乗数は 0.5 になります。定数 0.0 および乗数 1.0 は変更されません。




自動レイアウトでは、同じ問題を解決するために複数の方法が頻繁に提供されています。理想的には、目的を最も明確に表す解決策を選択する必要があります。ただし、さまざまなデベロッパが、どの解決策が最適であるかについては間違いなく意見が異なります。ここで、一貫していることは正しいことよりも優れています。アプローチを選択し、常にそれに固執する場合、長期的には問題が少なくなります。たとえば、このガイドでは以下の経験則を使用しています。


  1. 整数の乗数は、分数の乗数よりも好まれます。

  2. 正の定数は負の定数よりも好まれます。

  3. 可能な限り、ビューはレイアウト順に表示する必要があります:先端から後端へ、上端から下端へ。

明確で満足できるレイアウトの作成


自動レイアウトを使用する場合の目標は、考えられる解決策が 1 つだけある一連の方程式を提供することです。あいまいな制約には複数の解決策があります。満たされない制約には有効な解決策がありません。


一般に、制約は各ビューのサイズと位置の両方を定義しなければなりません。スーパービューのサイズがすでに設定されているとすると (たとえば、iOS のシーンのルートビュー)、明確で満足できるレイアウトでは、ビューごと寸法ごとに 2 つの制約が必要です (スーパービューはカウントしないで)。ただし、使用したい制約の選択に関しては、幅広いオプションがあります。たとえば、以下の 3 つのレイアウトはすべて、明確で満足できるレイアウトを生成します (水平方向の制約のみが示されています)。


constraint_examples_2x

各レイアウトには 1 つのビューと 2 つの水平の制約があることに注意してください。いずれの場合も、制約はビューの幅と水平位置の両方を完全に定義しています。つまり、すべてのレイアウトは、水平軸に沿って明確で満足できるレイアウトを生成します。ただし、これらのレイアウトは同様に有用ではありません。スーパービューの幅が変わるとどうなるかを考えてみましょう。


最初のレイアウトでは、ビューの幅は変わりません。ほとんどの場合、これはあなたが望むものではありません。実際、原則として、ビューに一定のサイズを割り当てることは避けてください。自動レイアウトは、環境に動的に適応するレイアウトを作成するように設計されています。ビューに固定サイズを与えるたびに、その能力を短絡させます。


明白ではないかもしれませんが、2 番目と 3 番目のレイアウトは同一の動作を生成します。どちらも、スーパービューの幅が変化しても、ビューとそのスーパービューの間に固定マージンを維持します。ただし、それらは必ずしも同じではありません。一般に、2 番目の例の方がわかりやすいですが、3 番目の例は、特にいくつかの項目を中央揃えにする場合に、より役立つ場合があります。いつものように、特定のレイアウトに最適なアプローチを選択してください。


もう少し複雑なことを考えてみましょう。iPhone に 2 つのビューを並べて表示したいとします。あなたはそれらがすべての側面に良いマージンを持っていること、そしてそれらが常に同じ幅を持っていることを確認したいとします。また、デバイスの回転に応じて、適切にサイズ変更します。


以下の図は、縦向き(portrait)と横向き(landscape)のビューを示しています。


Blocks_Portrait_2x


Blocks_Landscape_2x


では、これらの制約はどのように見えるでしょうか?以下の図は、1 つの簡単な解決策を示しています。


two_view_example_1_2x


上記の解決策では、以下の制約を使用しています。


 1    // Vertical Constraints
 2    Red.top = 1.0 * Superview.top + 20.0
 3    Superview.bottom = 1.0 * Red.bottom + 20.0
 4    Blue.top = 1.0 * Superview.top + 20.0
 5    Superview.bottom = 1.0 * Blue.bottom + 20.0
 6     
 7    // Horizontal Constraints
 8    Red.leading = 1.0 * Superview.leading + 20.0
 9    Blue.leading = 1.0 * Red.trailing + 8.0
10    Superview.trailing = 1.0 * Blue.trailing + 20.0
11    Red.width = 1.0 * Blue.width + 0.0


以前の経験則に従って、このレイアウトには 2 つのビュー、4 つの水平の制約、および 4 つの垂直の制約があります。これは完全なガイドではありませんが、正しい方向に進んでいることをすぐに示します。さらに重要なことに、制約は両方のビューのサイズと位置の両方を一意に指定し、明確で満足できるレイアウトを生成します。これらの制約のいずれかを削除すると、レイアウトがあいまいになります。追加の制約を追加すると、競合が発生するリスクがあります。


それでも、これが唯一の可能な解決策ではありません。同様に有効なアプローチを以下に示します。


two_view_example_2_2x


青いボックスの上部と下部をそのスーパービューに固定する代わりに、青いボックスの上部を赤いボックスの上部に揃えます。同様に、青いボックスの下部を赤いボックスの下部に揃えます。制約を以下に示します。


 1    // Vertical Constraints
 2    Red.top = 1.0 * Superview.top + 20.0
 3    Superview.bottom = 1.0 * Red.bottom + 20.0
 4    Red.top = 1.0 * Blue.top + 0.0
 5    Red.bottom = 1.0 * Blue.bottom + 0.0
 6     
 7    //Horizontal Constraints
 8    Red.leading = 1.0 * Superview.leading + 20.0
 9    Blue.leading = 1.0 * Red.trailing + 8.0
10    Superview.trailing = 1.0 * Blue.trailing + 20.0
11    Red.width = 1.0 * Blue.width + 0.0


この例には、2 つのビュー、4 つの水平の拘束、および 4 つの垂直の拘束がまだあります。それでも、明確で満足できるレイアウトが生成されます。


けど、どっちが良いの?

これらの解決策はどちらも有効なレイアウトを生成します。どっちが良いですか?


残念ながら、一方のアプローチがもう一方のアプローチよりも厳密に優れていることを客観的に証明することは事実上不可能です。それぞれに独自の長所と短所があります。


最初の解決策は、ビューが削除されたときに、より堅牢です。ビュー階層からビューを削除すると、そのビューを参照するすべての制約も削除されます。したがって、赤いビューを削除すると、青いビューには 3 つの制約がその場所に残るようにされます。1 つの制約のみを追加する必要があり、有効なレイアウトが再び得られます。2 番目の解決策では、赤いビューを削除すると、青いビューは 1 つの制約のみのままになります。


一方、最初の解決策では、ビューの上部と下部を揃える場合、上部と下部の制約が同じ定数値を使用していることを確認しなければなりません。1 つの定数を変更する場合は、他の定数も変更することを忘れないでください。




制約の不等式


これまでのところ、すべての例で制約は等式として示されていましたが、これは物語の一部にすぎません。制約は不等式も表すことができます。具体的には、制約の関係は、等しいか、以上か、以下かです。


たとえば、制約を使用してビューの最小サイズまたは最大サイズを定義できます (リスト 3-3)。


リスト 3-3 最小サイズと最大サイズの割り当て


 1    // Setting the minimum width
 2    View.width >= 0.0 * NotAnAttribute + 40.0
 3     
 4    // Setting the maximum width
 5    View.width <= 0.0 * NotAnAttribute + 280.0


不等式を使用し始めるやいなや、寸法ルールごとビューごとの 2 つの制約が解除されます。単一の等式関係を常に 2 つの不等式で置き換えることができます。リスト 3-4 では、単一の等式関係と不等式のペアが同じ動作を生成します。


リスト 3-4 単一の等式関係を 2 つの不等式で置き換える


 1    // A single equal relationship
 2    Blue.leading = 1.0 * Red.trailing + 8.0
 3     
 4    // Can be replaced with two inequality relationships
 5    Blue.leading >= 1.0 * Red.trailing + 8.0
 6    Blue.leading <= 1.0 * Red.trailing + 8.0


2 つの不等式が常に 1 つの等号関係に等しいとは限らないため、逆は常に真とは限りません。たとえば、リスト 3-3 の不等式は、ビューの幅の可能な値の範囲を制限しますが、それだけでは幅を定義しません。この範囲内でのビューの位置とサイズを定義するには、追加の水平の制約が必要です。


制約の優先順位


デフォルトでは、すべての制約が必要です。自動レイアウトは、すべての制約を満たす解決策を計算しなければなりません。それができない場合は、エラーが起こります。自動レイアウトは、満たされない制約に関する情報をコンソールに出力し、違反する制約の 1 つを選択します。次に、制約が壊れていない状態で解決策を再計算します。詳細については、満たされないレイアウト を参照してください。


オプションの制約を作成することもできます。すべての制約には、1〜1000 の間の優先順位があります。優先順位が 1000 の制約が必須です。他のすべての制約はオプションです。


解決策を計算するとき、自動レイアウトは優先順位の高いものから低いものへとすべての制約を満たそうとします。オプションの制約を満たすことができない場合、その制約はスキップされ、次の制約に進みます。


オプションの制約と不等式は、多くの場合、連携して機能します。たとえば、リスト 3-4 では、2 つの不等式に異なる優先順位を指定できます。[以上(greater-than-or-equal)] の関係が必須の場合があり (優先度 1000)、[以下(less-than-or-equal)] の関係の優先度は低い (優先度 250)です。これは、青いビューが赤いビューから 8.0 ポイントより近くなることはできないことを意味します。ただし、他の制約により、それをさらに引き離すことができます。それでも、オプションの制約により、レイアウトの他の制約が与えられている場合、青色のビューが赤色のビューに引き寄せられ、8.0 ポイントの間隔にできる限り近くなります。


注意:

1000 の優先度の値すべてを使用する義務を負わないでください。実際、優先順位は、システム定義の低 (250)、中 (500)、高 (750)、および必須 (1000) の優先順位の周りに一般的なクラスターを配置する必要があります。結合を防ぐために、これらの値よりも 1 ポイントか 2 ポイント高いか低い制約を作成する必要がある場合があります。それをはるかに超える場合は、おそらくレイアウトのロジックを再検討する必要があります。


iOS で事前に定義された制約定数のリストについては、UILayoutPriority 列挙型をご覧ください。OS Xについては、レイアウト優先度定数を参照してください。




固有のコンテンツサイズ


これまでのすべての例では、ビューの位置とそのサイズの両方を定義するために制約を使用してきました。ただし、一部のビューは、現在のコンテンツを考慮して自然なサイズになっています。これは、固有のコンテンツサイズ と呼ばれます。たとえば、ボタンの固有のコンテンツサイズは、タイトルに小さなマージンを加えたサイズです。


すべてのビューに固有のコンテンツサイズがあるわけではありません。ビューがそうである場合、固有のコンテンツサイズは、ビューの高さ、幅、またはその両方を定義できます。いくつかの例を表 3-1 に示します。


表 3-1 共通コントロールの固有のコンテンツサイズ


View固有のコンテンツサイズ
UIView と NSView固有のコンテンツサイズはありません。
スライダー幅のみを定義します (iOS)。
スライダーの型に応じて、幅、高さ、またはその両方を定義します (OS X)。
ラベル、ボタン、スイッチ、テキストフィールド高さと幅の両方を定義します。
テキストビューとイメージビュー固有のコンテンツサイズは異なる場合があります。


固有のコンテンツサイズは、ビューの現在のコンテンツに基づいています。ラベルまたはボタンの固有のコンテンツサイズは、表示されるテキストの量と使用されるフォントに基づいています。他のビューの場合、固有のコンテンツサイズはさらに複雑です。たとえば、空の画像ビューには固有のコンテンツサイズはありません。ただし、画像を追加するとすぐに、その固有のコンテンツサイズが画像のサイズに設定されます。


テキストビューの固有のコンテンツサイズは、コンテンツによって異なり、スクロールが有効になっているかどうか、およびビューに適用されているその他の制約によって異なります。たとえば、スクロールを有効にすると、ビューには固有のコンテンツサイズがありません。スクロールを無効にすると、デフォルトで、ビューの固有のコンテンツサイズは、行の折り返しなしのテキストのサイズに基づいて計算されます。たとえば、テキストに改行がない場合、コンテンツを 1 行のテキストとしてレイアウトするために必要な高さと幅が計算されます。制約を追加してビューの幅を指定する場合、固有のコンテンツサイズは、その幅を与えたテキストを表示するために必要な高さを定義します。


自動レイアウトは、各次元の一対の制約を使用して、ビューの固有のコンテンツサイズを表します。コンテンツをきつく固定すると、ビューが内側に引っ張られ、コンテンツの周囲にぴったり収まります。圧縮抵抗によってビューが外側に押し出され、コンテンツが揃えられなくなります。


intrinsic_content_size_2x


これらの制約は、リスト 3-5 に示す不等式を使用して定義されています。ここで、IntrinsicHeight および IntrinsicWidth 定数は、ビューの固有のコンテンツサイズからの高さと幅の値を表します。


リスト 3-5 圧縮抵抗とコンテンツ固定 (Content-Hugging) の方程式


 1    // Compression Resistance
 2    View.height >= 0.0 * NotAnAttribute + IntrinsicHeight
 3    View.width >= 0.0 * NotAnAttribute + IntrinsicWidth
 4     
 5    // Content Hugging
 6    View.height <= 0.0 * NotAnAttribute + IntrinsicHeight
 7    View.width <= 0.0 * NotAnAttribute + IntrinsicWidth


これらの制約はそれぞれ独自の優先順位を持つことができます。デフォルトでは、ビューはそのコンテンツの固定に 250 の優先度を使用し、圧縮抵抗に 750 の優先度を使用します。したがって、ビューを縮小するよりもビューを拡大する方が簡単です。ほとんどのコントロールでは、これが望ましい動作です。たとえば、ボタンをその本来のコンテンツサイズよりも安全に拡大できます。ただし、縮小すると、そのコンテンツがクリップされる場合があります。Interface Builder は、これらの優先度を時々変更して、つながりを防ぐのを助けるかもしれないことに注意してください。詳細については、内容の保持と圧縮耐性の優先順位の設定 を参照してください。


可能な限り、レイアウトではビューの固有のコンテンツサイズを使用してください。これにより、ビューのコンテンツが変化したときにレイアウトを動的に適応させることができます。また、明確で競合のないレイアウトを作成するために必要な制約の数を減らせますが、ビューのコンテンツの固定と圧縮抵抗 (CHCR) の優先順位を管理する必要があります。固有のコンテンツサイズを処理するためのガイドラインを以下に示します。


固有のコンテンツサイズ対ちょうど良いサイズ


固有のコンテンツサイズは、自動レイアウトへの入力として機能します。ビューに固有のコンテンツサイズがある場合、システムはそのサイズを表す制約を生成し、制約はレイアウトの計算に使用されます。


一方、ちょうどいいサイズは、自動レイアウトエンジンからの出力です。これは、ビューの制約に基づいてビューに対して計算されたサイズです。ビューが自動レイアウトを使用してサブビューをレイアウトする場合、システムはそのコンテンツに基づいてビューのちょうどいいサイズを計算できます。


スタックビューが良い例です。他の制約がなければ、システムはコンテンツと属性に基づいてスタックビューのサイズを計算します。多くの点で、スタックビューは固有のコンテンツサイズがあるかのように機能します。1 つの垂直の制約と 1 つの水平の制約のみを使用して有効なレイアウトを作成し、その位置を定義できます。しかし、そのサイズは自動レイアウトによって計算されます。自動レイアウトへの入力ではありません。スタックビューには固有のコンテンツサイズがないため、スタックビューの CHCR 優先度を設定しても効果はありません。


スタックビューの外側の項目に対してスタックビューのちょうどいいサイズを調整する必要がある場合は、明示的な制約を作成してそれらの関係をキャプチャするか、スタックの外側の項目に対してスタックのコンテンツの CHCR 優先順位を変更します。


値の解釈


自動レイアウトの値は常にポイント単位です。ただし、これらの測定値の正確な意味は、関連する属性とビューのレイアウト方向によって異なります。


自動レイアウトの属性ノート
height 高さ
Width 幅
ビューのサイズ。これらの属性には定数値を割り当てるか、他の高さと幅の属性と組み合わせることができます。これらの値を負にすることはできません。
TopTop 上端
Bottom 下端
Baseli ベースライン
スクリーンを下に移動すると、値が増加します。これらの属性は、中揃え Y、上端、下端、およびベースライン属性とのみ組み合わせることができます。
Leadin 先端
Traill 後端
値は、後縁に向かって移動すると増加します。レイアウトの方向が左から右の場合、値は右に移動すると増加します。レイアウトの方向が右から左の場合、値は左に移動すると増加します。これらの属性は、先端、後端、または中揃え X 属性とのみ組み合わせることができます。
Leadin 左
Traill 右
値は、右に行くほど大きくなります。これらの属性は、左、右、および 中揃え X 属性とのみ組み合わせられます。
左および右属性の使用は避けてください。代わりに先端および後端を使用してください。これにより、レイアウトをビューの読み取り方向に合わせられます。
デフォルトでは、読む方向はユーザが設定した現在の言語に基づいて決定されます。ただし、必要に応じてこれを上書きできます。iOS では、制約を保持するビュー (制約の影響を受けるすべてのビューの最も近い共通の祖先) に semanticContentAttribute プロパティを設定して、左から右への言語と右から左への言語を切り替えるときにコンテンツのレイアウトを反転するかどうかを指定します。
CenteX 中揃え X
Baseli 中揃え Y
解釈は、方程式の他の属性に基づいています。中揃え Xは、中揃え X、先端、後端、右、左の各属性と組み合わせることができます。
中揃え Yは、中揃え Y、上、下、およびベースライン属性と組み合わせることができます。


前:制約のない自動レイアウト 次:Interface Builder での制約の操作
































































目次
Xcode の新機能

  • 始めましょう

  • 自動レイアウトガイド全メニュー

  • 自動レイアウトの理解
  • 制約のない自動レイアウト
  • 制約の構造
  • 自動レイアウト属性
    方程式の例
    代入ではなく等式
    明確で満足できるレイアウトの作成
    制約の不等式
    制約の優先順位
    固有のコンテンツサイズ
    固有のコンテンツサイズ対ちょうど良いサイズ
    値の解釈
  • Interface Builder での制約の操作

  • 自動レイアウトレシピ集

  • 自動レイアウトのデバッグ

  • 高度な自動レイアウト

  • 付録

  • 改訂記録











  • トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ









    トップへ