Xamarin Designer for iOS を使用した自動レイアウト

警告

iOS Designer は、Visual Studio 2019 バージョン 16.8 および Visual Studio 2019 for Mac バージョン 8.8 で非推奨とされ、Visual Studio 2019 バージョン 16.9 および Visual Studio for Mac バージョン 8.9 から削除されています。 iOS ユーザー インターフェイスを構築するのに推奨される方法は、Xcode を実行している Mac 上で直接作業を行うことです。 詳細については、「Xcode を使用したユーザーインターフェイスの設計」を参照してください。

自動レイアウト ("アダプティブ レイアウト" ともいう) は、応答性の高い設計アプローチです。 各要素の位置が画面上のポイントにハードコーディングされている切り替えレイアウト システムとは異なり、自動レイアウトは、デザイン 画面上での要素の他の要素に対する相対的な位置という "リレーションシップ" に関わります。 自動レイアウトの中心にあるのは、画面上の他の要素のコンテキストにおける要素または要素のセットの配置を定義する制約 (ルール) の概念です。 要素が画面上の特定の位置に縛られていないため、さまざまな画面サイズとデバイスの向きに適したアダプティブ レイアウトを作成するのに制約を活用することができます。

このガイドでは制約と、Xamarin iOS Designer での制約に関する作業方法について説明します。 このガイドでは、プログラムによる制約の操作については取り上げません。 自動レイアウトのプログラムによる使用については、Apple のドキュメントを参照してください。

要件

Xamarin Designer for iOS は、Visual Studio for Mac および Windows では Visual Studio 2017 以降で利用できます。

このガイドは、「iOS Designer の基本」ガイドに載っているDesigner のコンポーネントに関する知識を前提としています。

制約の概要

制約は、画面上の 2 つの要素間のリレーションシップの数学的表現です。 UI 要素の位置を数学的リレーションシップとして表すことで、UI 要素の位置のハード コーディングに絡むいくつかの問題が解決されます。 たとえば、縦長モードで画面の下部から 20px にボタンを配置すると、横長モードではボタンの位置は画面外になります。 これを回避するために、ボタンの下端をビューの下部から 20px に配置する制約を設定できます。 ここでボタンの端の位置は、button.bottom = view.bottom - 20px として計算されます。これにより、縦長モードでも横長モードでも、ビューの下部から 20px にボタンが配置されます。 数学的なリレーションシップに基づいて配置を計算できることで、UI デザインでは制約が非常に有用なものとなっています。

制約を設定する場合、制約対象のオブジェクト、および制約が作用するプロパティ ("属性") を引数として取る NSLayoutConstraint オブジェクトを作成します。 iOS Designer では、属性には要素の"左"、"右"、"上"、"下"などの端が含まれます。 また、"高さ" と "幅"、中心点の位置 (centerXcenterY) などのサイズ属性も含まれます。 たとえば、2 つのボタンの左境界の位置に関する制約を追加すると、Designer の内部で次のコードが生成されます。

View.AddConstraint (NSLayoutConstraint.Create (Button1, NSLayoutAttribute.Left, NSLayoutRelation.Equal, Button2, NSLayoutAttribute.Left, 1, 10));

次のセクションでは、自動レイアウトの有効化と無効化、制約ツール バーの使用など、iOS Designer を使用した制約の操作について説明します。

自動レイアウトを有効にする

デフォルトの iOS Designer 構成では、制約モードが有効になっています。 ただし、手動で有効または無効にする必要がある場合は、次の 2 つのステップで行うことができます。

  1. デザイン画面の空の領域をクリックします。 これにより、要素の選択が解除され、ストーリーボード ドキュメントのプロパティが表示されます。

  2. プロパティ パネルの [Autolayout を使用する] チェック ボックスをオンまたはオフにします。

    The Use Autolayout checkbox in the property panel

デフォルトでは、制約は画面上に作成または表示されません。 代わりに、コンパイル時にフレーム情報から自動的に推論されます。 制約を追加するには、デザイン画面で要素を選択し、それに制約を追加する必要があります。 これは、制約ツール バーを使用して行うことができます。

制約ツール バー

The Context Menu Commands

制約ツール バーが更新されたため、現在は次の 2 つのメイン部分で構成されています。

  • 制約モードのトグル ボタン: 以前は、デザイン画面で選択したビューをもう一度クリックすることで制約モードに入りました。 現在は、制約バーで次のようにトグル ボタンを使用します。

    contraints modes toggle

  • "制約更新" ボタン: 制約編集モードかどうかに応じて変わることに注意してください。

    • 制約編集モードでは、このボタンは要素フレームに合わせて制約を調整します。
    • フレーム編集モードでは、このボタンは制約が定義する位置に合わせて要素フレームを調整します。

制約編集のポップオーバー

制約エディターのポップアップを使用すると、選択したビューで複数の制約を一度に追加して更新できます。 複数間隔、縦横比、および 2 つのビューの左端でビューを揃えるなどの配置制約を作成できます。

選択したビューで制約を編集するには、省略記号をクリックしてポップオーバーを表示します。constraints editing popover

制約ポップオーバーを開くと、事前設定された制約がビューに表示されます。 右上隅のコンボ ボックスから [All Sides] (すべての辺) を選択して、すべての間隔制約を設定できます。[Clear All] (すべてクリア) を選択すると、それを解除できます。

[W] は幅の、[H] は高さの制約を設定します。 [縦横比] にチェックを入れると、ビューの高さと幅がさまざまな画面サイズに応じて制御されます。ビューの幅は、比率の分子として、高さは分母として使用されます。

constraints spacing

間隔制約の 4 つのコンボ ボックスでは、隣接するビューが制約を固定するように表示されます

画面ベースの制約編集

よりきめ細かく制約の編集を行う場合は、デザイン画面で直接、制約を操作できます。 このセクションでは、ピン間隔コントロール、ドロップ領域、さまざまな種類の制約の操作など、画面ベースの制約編集の基本について説明します。

制約の作成

iOS Designer ツールには、デザイン画面上の要素を操作するための 2 種類のコントロールが用意されています。 それは次の図に示す、"ドラッグ コントロール" と "ピン間隔コントロール" です。

view controls

これは、制約バーの制約モード ボタンを選択することで切り替えられます。

要素の各辺にある 4 つの T 型ハンドルは、要素の "上端"、"右端"、"下端"、"左端"の制約を定義します。 要素の右側と下部にある 2 つの I 型ハンドルは、それぞれ "高さ" と "幅" の制約を定義します。 中央の正方形は、centerXcenterY の両方の制約を処理します。

制約を作成するには、ハンドルを選択し、デザイン画面上のどこかにドラッグします。 ドラッグを開始すると、一連の緑色の線/ボックスが画面に表示されて、制約できる内容を示します。 たとえば、次のスクリーンショットでは、中央のボタンの上辺の制約を行っています。

Constraining the top side of the middle button

他の 2 つのボタンを横切っている緑色の 3 つの破線に注目してください。 この緑色の線は、"ドロップ領域"、または制約できる他の要素の属性を示しています。 上のスクリーンショットでは、他の 2 つのボタンに、対象のボタンを制約する 3 つの垂直のドロップ領域 ("下"、centerY、"上") があります。 ビューの上部にある緑色の破線は、ビュー コントローラーによりビューの上部に制約が設けられていること、緑の実線ボックスはビュー コントローラーにより上部レイアウト ガイドの下に制約が設けられていることを意味しています。

重要

レイアウト ガイドは特殊な種類の制約ターゲットであり、ステータス バーやツールバーなどのシステム バーの存在を考慮した上部と下部の制約を作成できます。 主な用途の 1 つは、iOS 6 と iOS 7 の間でアプリに互換性を持たせることです (最新バージョンのコンテナー ビューがステータス バーの下に拡張されているため)。 上部レイアウト ガイドの詳細については、Apple のドキュメントを参照してください。

次の 3 つのセクションでは、さまざまな種類の制約の操作について説明します。

サイズの制約

サイズの制約 ("高さ" と "幅") には、2 つのオプションがあります。 1 つ目のオプションは、上の例に示すように、ハンドルをドラッグして隣接要素サイズへの制約を行うことです。 もう 1 つのオプションは、ハンドルをダブルクリックして自己制約を作成することです。 これにより、次のスクリーンショットに示すように、定数サイズの値を指定できます。

Drag the handle to constrain to a neighbor element size, as illustrated here

中心の制約

正方形のハンドルは、コンテキストに応じて centerX または centerY の制約を作成します。 次のスクリーンショットに示すように、正方形のハンドルをドラッグすると、他の要素がハイライト表示され、垂直方向と水平方向の両方のドロップ領域が提示されます。

Center Constraints

垂直ドロップ領域を選択すると、centerY 制約が作成されます。 水平ドロップ領域を選択した場合、制約は centerX に基づきます。

組み合わせ制約

2 つの要素間に配置とサイズ等価性の両方の制約を作成するには、次のスクリーンショットに示すように、上部のツール バーから項目を選択して、順に、水平方向の配置、垂直方向の配置、サイズの等価性を指定できます。

Combinational Constraints

制約の視覚化と編集

制約を追加する場合、項目を選択すると、次のようにデザイン画面に制約が青色の線として表示されます。

Visualizing Constraints

青い線をクリックして制約を選択し、プロパティ パネルで直接、制約値を編集できます。 または次のように、青い線をダブルクリックしてポップオーバーを表示することで、デザイン画面で値を直接、編集することができます。

Editing Constraints

制約の問題

制約の使用において、いくつかの種類の問題が発生する場合があります。

  • 制約の競合 — これは、複数の制約によって要素の属性が競合する値を持ってしまい、制約エンジンがそれらを調整できない場合に発生します。
  • 制約が不十分な項目 — 制約が有効であるためには、要素のプロパティ (位置 + サイズ) が、制約のセットと内在サイズにより完全にカバーされている必要があります。 これらの値があいまいな場合、項目の制約が不十分であるといいます。
  • フレームの誤配置 - これは、要素のフレームとその制約のセットが 2 つの異なる四角形を定義し生じさせる場合に発生します。

このセクションでは、上記の 3 つの問題について詳しく説明し、その対処方法の詳細を取り上げます。

制約の競合

制約の競合は赤色で表示され、警告記号が付いています。 警告記号の上にマウス ポインターを合わせると、競合に関する情報が記されたポップオーバーが表示されます。

Conflicting Constraints warning

制約が不十分な項目

制約が不十分な項目がオレンジ色で表示され、ビュー コントローラー オブジェクト バーにオレンジ色のマーカー アイコンが出現します。

Underconstrained items appear in orange

このマーカー アイコンをクリックすると、次のスクリーンショットに示されるように、シーン内の制約が不十分な項目に関する情報が得られるので、制約を完全なものにするか、制約を削除することで問題を解決できます。

Fixing Underconstrained Items

フレームの誤配置

フレームの誤配置では、制約が不十分な項目と同じカラー コードが使用されます。 項目は常にネイティブ フレームを使用して画面にレンダリングされますが、フレームの誤配置の場合には、次のスクリーンショットに示されるように、アプリケーションの実行時に項目が置かれることになる場所が赤い四角形で示されます。

Sample Frame Misplacement view

フレームの誤配置エラーを解決するには、制約ツールバーの制約に基づいてフレームを更新ボタン (右端の ボタン) を選択します。

Update Frames based on Constraints toolbar button

これにより、コントロールによって定義された位置に合わせて要素フレームが自動的に調整されます。

コード内の制約の変更

アプリの要件に基づいて、コード内の制約の変更が必要となる場合があります。 たとえば、制約がアタッチされているビューのサイズ変更や位置変更、制約の優先度の変更、制約の完全な非アクティブ化などです。

コード内の制約にアクセスするには、まず、次の手順を実行して iOS Designer で制約を表示させる必要があります。

  1. (上記のいずれかの方法を使用して) 通常どおりに制約を作成します。

  2. ドキュメント アウトライン エクスプローラーで、目的の制約を探して選択します。

    The Document Outline Explorer

  3. 次に、プロパティ エクスプローラー[ウィジェット] タブの制約に名前を割り当てます。

    The Widget Tab

  4. 変更を保存します。

上記の変更が行われたら、コード内の制約にアクセスし、そのプロパティを変更できます。 たとえば、次のコマンドを使用して、アタッチされたビューの高さを 0 に設定できます。

ViewInfoHeight.Constant = 0;

iOS Designer で制約に対する次の設定を指定します。

Editing a Constraint in the Property Explorer

遅延レイアウト パス

制約の変更に応じてアタッチされたビューを即座に更新する代わりに、自動レイアウト エンジンでは近い将来の "遅延レイアウト パス" をスケジュール設定します。 この遅延パスでは、指定されたビューの制約が更新されるだけでなく、階層内のすべてのビューの制約が新しいレイアウトに合わせて再計算され、更新されます。

親ビューの SetNeedsLayout メソッドまたは SetNeedsUpdateConstraints メソッドを呼び出すことで、いつでも独自の遅延レイアウト パスをスケジュール設定できます。

遅延レイアウト パスは、ビュー階層全体で 2 つの一意のパスから構成されます。

  • 更新パス - このパスでは、自動レイアウト エンジンはビュー階層を走査し、すべてのビュー コントローラーで UpdateViewConstraints メソッドを呼び出し、すべてのビューで UpdateConstraints メソッドを呼び出します。
  • レイアウト パス - このパスでも、自動レイアウト エンジンはビュー階層を走査しますが、今回はすべてのビュー コントローラーで ViewWillLayoutSubviews メソッドを呼び出し、すべてのビューで LayoutSubviews メソッドを呼び出します。 この LayoutSubviews メソッドは、自動レイアウト エンジンによって計算された四角形によって、各サブビューの Frame プロパティを更新します。

制約の変更のアニメーション化

制約プロパティの変更に加えて、Core Animation を使用してビューの制約に対する変更をアニメーション化できます。 次に例を示します。

UIView.BeginAnimations("OpenInfo");
UIView.SetAnimationDuration(1.0f);
ViewInfoHeight.Constant = 237;
View.LayoutIfNeeded();

//Execute Animation
UIView.CommitAnimations();

ここで重要なのは、アニメーション ブロックの内部で親ビューの LayoutIfNeeded メソッドを呼び出すことです。 これは、アニメーション化された位置またはサイズの変更の各 "フレーム" を描画するようにビューに指示します。 この行がない場合、ビューはアニメーション化せずに最終的なバージョンにスナップします。

まとめ

このガイドでは、iOS の自動 (または "アダプティブ") レイアウトと、デザイン画面上の要素間のリレーションシップの数学的表現としての制約の概念について説明しました。 そこでは、iOS Designer で自動レイアウトを有効にする方法、制約ツール バーの操作、デザイン 画面での個々の制約の編集について取り上げました。 次いで、3 つの一般的な制約の問題をトラブルシューティングする方法について説明しました。 最後に、コード内の制約を変更する方法を示しました。