ビューのサイズを指定する
- 7 分
複数のデバイス全体で一貫したユーザー インターフェイスを設計するのは困難です。これは、デバイスのサイズと、ピクセルの密度が異なる場合があるためです。 モバイル、タブレット、デスクトップなど、使用できるさまざまなデバイスについて考えてみます。 それぞれで外観が同じようなユーザー インターフェイスをどのように作成しますか。
.NET Multi-Platform App UI (MAUI) では、一貫性のあるユーザー インターフェイスを構築するのに役立つレイアウト パネルが提供されます。 レイアウト パネルには、その子のビューのサイズと位置を設定する役割があります。 このユニットでは、.NET MAUI でのレイアウト システムのしくみについて学習します。 特に、既定でビューのサイズが設定される方法、実行時にビューの特定のサイズと位置を要求する方法を紹介します。
レイアウト パネルとは
レイアウト パネルは、子ビューのコレクションを保持し、そのサイズと位置を決定する .NET MAUI コンテナーです。 レイアウト パネルでは、ユーザーがデバイスを回転させたときなど、アプリのサイズが変更されたときに自動的に再計算を行います。
注
"ビュー" または "子ビュー" という用語は、レイアウト パネルに配置されたコントロールを指します。 ビューには、ラベル、ボタン、エントリ フィールド、または .NET MAUI でサポートされているその他の種類のビジュアル要素を指定できます。
.NET MAUI には、選択可能な複数のレイアウト パネルがあります。 各パネルでは、その子ビューを異なる方法で管理します。 次の図には、最も一般的なオプションのいくつかの概念の概要が示されています。
-
StackLayout: 単一の行または列にその子ビューを配置します。StackLayoutに加え、向きを変更する必要がないときのために最適化されたVerticalStackLayoutとHorizontalStackLayoutもあります。 -
AbsoluteLayout: x と y 座標を使って、その子ビューを配置します。 -
Grid: 行と列の交差部分から作成されるセルにその子ビューを配置します。 -
FlexLayout: 1 つの行または列に収まらない場合にラップできる点を除いて、StackLayoutのように子ビューを配置します。
注
RelativeLayout と呼ばれる 5 番目のレイアウト パネルもあり、子ビューを相互に相対的に配置する方法を指定できます。 パフォーマンスが向上するため、FlexLayout の代わりに RelativeLayout コントロールを使う必要があります。
RelativeLayout は、以前の Xamarin アプリとの下位互換性を確保するため、.NET MAUI に含まれています。
.NET MAUI のページを構築する一般的なプロセスは、レイアウト パネルを作成してから子ビューをそこに追加することです。 ビューをレイアウトに追加すると、そのサイズと位置に影響する可能性があります。 しかし、最終的な決定は、パネルでその内部のレイアウト アルゴリズムに基づいて行われます。
ビューの特定のサイズを要求できる方法を見る前に、レイアウト システムで既定でビューのサイズが設定されるしくみを確認しましょう。
ビューの既定のサイズ
ビューのサイズを指定しない場合は、コンテンツの周囲に合う十分な大きさに自動的に拡大されます。 たとえば、次の Extensible Application Markup Language (XAML) について考えてみます。
<Label
Text="Hello"
BackgroundColor="Silver"
VerticalOptions="Center"
HorizontalOptions="Center"
FontSize="40"/>
この例では、Hello という単語がシルバーの背景で表示されるように、ラベルを定義します。 サイズを指定していないため、ラベルは単語 Helloの周囲に合わせて自動的にサイズ変更されます。 次の画像は、Android デバイスでレンダリングされたラベルの図です。
注
ラベルの背景色を設定できると、実行時の大きさを決定するの役立ちます。 これは、UI を構築するときに留意すべき、良いデバッグ技法です。
ビューのサイズを指定する
UI を構築するときに、ビューのサイズの制御が必要になるのが一般的です。 たとえば、サインイン ページを構築し、サインイン ボタンを画面のちょうど半分の幅にするとします。 ビューの既定のサイズを使用した場合、ボタンは "サインイン" というテキストのサイズのみとなります。 そのサイズは十分な大きさではないため、自分でサイズを指定する必要があります。
View 基底クラスでは、ビューのサイズに影響する WidthRequest および HeightRequest という 2 つのプロパティが定義されます。
WidthRequest では幅を指定でき、HeightRequest では高さを指定することができます。 両方のプロパティの型は double です。
以下は、XAML でラベルの幅と高さを指定する方法を示す例です。
<Label
Text="Hello"
BackgroundColor="Silver"
VerticalOptions="Center"
HorizontalOptions="Center"
WidthRequest="100"
HeightRequest="300"
FontSize="40"/>
結果は次のようになります。
注
ラベルのテキストはラベルの中央にありませんが、ラベルはやはり中央揃えです。
注目すべき 1 つの点は、これらのプロパティの名前です。 両方のプロパティに request という単語が含まれています。 この単語は、レイアウト パネルでは実行時にそれらが優先されない場合があることを意味しています。 レイアウト パネルでは、そのサイズの計算中にこれらの値を読み取り、可能な場合は、要求への対応を試みます。 十分なスペースがない場合、レイアウト パネルで値を無視することができます。
サイズの単位
WidthRequest と HeightRequest を設定するときは、100 のようなリテラル値を使います。 .NET MAUI レベルでは、これらの値に単位はありません。 ポイントでもピクセルでもありません。
double 型の単なる値です。 .NET MAUI によって、実行時に基になるオペレーティング システムにこれらの値が渡されます。 これは、数値の意味を判断するために必要なコンテキストを提供するオペレーティング システムです。
- iOS では、値は "ポイント" と呼ばれます。
- Android では、"密度非依存ピクセル" です。
ビューのレンダリングされたサイズ
ビューのサイズの決定はレイアウト パネルに依存するため、WidthRequest や HeightRequest を使用して、実行時の実際のサイズを示すことはできません。 たとえば、ラベルの WidthRequest を 100 に設定したものの、パネルには要求を満たすのに十分なスペースがないとします。 代わりに、パネルではラベルに 80 という幅が指定されます。 この時点で、WidthRequest プロパティの値を確認すると、レンダリングされた値が 100 であっても、80 と示されます。
この問題を解決するため、View 基底クラスでは、Width および Height という他の 2 つのプロパティが定義されています。 これらのプロパティの型は double であり、ビューのレンダリングされた幅と高さを表します。 ビューのサイズを取得するときは常に、Width および Height プロパティを使います。
ビューの位置を指定する
ビューの位置を設定する必要もあります。 たとえば、サインイン ページの例でのそれを思い出してください。この例では、サインイン ボタンが画面の半分の幅になるようにサイズを設定する必要がありました。 サインイン ボタンが画面の全幅ではないため、移動できるスペースがある程度があります。 画面の左側、右側、あるいは中央に配置することができます。
View 基底クラスには、VerticalOptions および HorizontalOptions という 2 つのプロパティがあります。これらを使用して、ビューの位置を設定します。 これらの設定は、レイアウト パネルによって割り当てられた四角形内でビューがどのように配置されるかに影響します。 四角形の 4 つの端のいずれかにビューを配置するように指定できます。 または、四角形全体を占有する必要があります。
VerticalOptions または HorizontalOptions の値を指定するのは、サイズを設定するより難しくなります。これらの型が LayoutOptions であるためです。
LayoutOptions 型とは
LayoutOptions は、Alignment および Expands という 2 つのレイアウト設定をカプセル化する、C# 型です。 両方のプロパティは配置に関連しますが、相互には関連しません。 型の定義は次のようになります。
public struct LayoutOptions
{
public LayoutAlignment Alignment { get; set; }
public bool Expands { get; set; }
...
}
次に、最も一般的で直感的なレイアウト オプションであるため、Alignment をさらに詳しく説明します。
LayoutAlignment 列挙型とは
LayoutAlignment は、Start、Center、End、Fill という 4 つの値を含む列挙型です。 これらの値を使用して、子ビューが、そのレイアウト パネルによって指定された四角形内でどのように配置されるかを制御することができます。 たとえば、次のコードと Android のスクリーンショットについて考えてみます。
<StackLayout>
<Label Text="Start" HorizontalOptions="Start" BackgroundColor="Silver" FontSize="40" />
<Label Text="Center" HorizontalOptions="Center" BackgroundColor="Silver" FontSize="40" />
<Label Text="End" HorizontalOptions="End" BackgroundColor="Silver" FontSize="40"/>
<Label Text="Fill" HorizontalOptions="Fill" BackgroundColor="Silver" FontSize="40"/>
</StackLayout>
この例では、縦方向の StackLayout を使っているため、各子ビューに行が指定されています。
HorizontalOptions によって、その行内のビューの位置が決まります。
Expands とは
LayoutOptions 構造体の 2 つ目のプロパティは、Expands です。
Expands プロパティは、Xamarin.Forms で bool 内のビューが追加のスペース (使用可能なものがある場合) を要求できるようにする StackLayout です。 このプロパティは廃止され、.NET MAUI では使用されなくなりました。 後ほど、Grid レイアウトのユニットで、同じ種類の展開を実現する方法を探ります。