Xamarin.Forms レイアウトを選ぶ

Xamarin.Forms レイアウト クラスを使うと、アプリケーション内で UI コントロールを配置し、グループ化することができます。 レイアウト クラスを選択するには、レイアウトの子要素の配置方法と、レイアウトの子要素のサイズを理解する必要があります。 さらに、レイアウトを入れ子にして目的のレイアウトを作成することが必要な場合があります。

次の画像は、メインの Xamarin.Forms レイアウト クラスで実現できる一般的なレイアウトを示しています。

Xamarin.Forms のメイン レイアウト クラス

StackLayout

StackLayout は、1 次元のスタックにある要素を水平方向または垂直方向に整理します。 この Orientation プロパティは要素の方向を指定します。既定の向きは Vertical です。 StackLayout は通常、ページ上の UI のサブセクションを配置するために使用します。

次の XAML は、3 つの Label オブジェクトを含む垂直方向の StackLayout の作成方法を示しています。

<StackLayout Margin="20,35,20,25">
    <Label Text="The StackLayout has its Margin property set, to control the rendering position of the StackLayout." />
    <Label Text="The Padding property can be set to specify the distance between the StackLayout and its children." />
    <Label Text="The Spacing property can be set to specify the distance between views in the StackLayout." />
</StackLayout>

StackLayout で要素のサイズが明示的に設定されていない場合、使用可能な幅 (Orientation プロパティの設定が Horizontal であれば高さ) に合わせて拡張されます。

StackLayout は通常、他の子レイアウトを含む親レイアウトとして使用します。 ただし、StackLayout オブジェクトの組み合わせを使用して Grid レイアウトを再現する場合は、StackLayout を使用しないでください。 次のコード例は、正しくない使用方法です。

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Details.HomePage"
             Padding="0,20,0,0">
    <StackLayout>
        <StackLayout Orientation="Horizontal">
            <Label Text="Name:" />
            <Entry Placeholder="Enter your name" />
        </StackLayout>
        <StackLayout Orientation="Horizontal">
            <Label Text="Age:" />
            <Entry Placeholder="Enter your age" />
        </StackLayout>
        <StackLayout Orientation="Horizontal">
            <Label Text="Occupation:" />
            <Entry Placeholder="Enter your occupation" />
        </StackLayout>
        <StackLayout Orientation="Horizontal">
            <Label Text="Address:" />
            <Entry Placeholder="Enter your address" />
        </StackLayout>
    </StackLayout>
</ContentPage>

不要なレイアウト計算が行われるため、不経済です。 代わりに Grid を使用して、必要なレイアウトをより適切に実現できます。

ヒント

StackLayout を使う場合は、LayoutOptions.Expands に設定する子要素を 1 つだけにしてください。 このプロパティにより、指定された子は、StackLayout がそれに与えられる最大の領域を占有します。このような計算を複数回実行することは無駄です。

詳細については、「Xamarin.Forms StackLayout」を参照してください。

グリッド

Grid は要素を行と列で表示するために使用します。行と列は比例サイズまたは絶対サイズを設定できます。 グリッドの行と列は、RowDefinitionsColumnDefinitions プロパティで指定します。

特定の Grid セルに要素を配置するには、Grid.ColumnGrid.Row の添付プロパティを使用します。 要素を複数の行と列にまたがるようにするには、Grid.RowSpanGrid.ColumnSpan の添付プロパティを使用します。

Note

Grid レイアウトとテーブルを混同しないでください。これは表形式のデータを表示するためのものではありません。 HTML テーブルとは異なり、Grid はコンテンツをレイアウトするためのものです。 表形式のデータを表示するには、ListViewCollectionView、または TableView を使うことを検討してください。

次の XAML は、2 つの行と 2 つの列を含む Grid を作成する方法を示しています。

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="50" />
        <RowDefinition Height="50" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>    
    <Label Text="Column 0, Row 0"
           WidthRequest="200" />
    <Label Grid.Column="1"
           Text="Column 1, Row 0" />
    <Label Grid.Row="1"
           Text="Column 0, Row 1" />
    <Label Grid.Column="1"
           Grid.Row="1"
           Text="Column 1, Row 1" />
</Grid>

この例では、サイズ設定は次のように機能します。

  • 各行の明示的な高さは、デバイスに依存しない 50 単位です。
  • 最初の列の幅は Auto に設定されているため、その子に必要な幅と同じになります。 この場合、最初の Label の幅にするため、デバイスに依存しない 200 単位の幅になります。

自動サイズ設定を使用すると、列または行内でスペースを分散でき、列と行のサイズをコンテンツに合わせて調整できます。 これを実行するには、RowDefinition の高さ、または ColumnDefinition の幅を Auto に設定します。 比例サイズ設定を使用して、グリッドの行と列に使用可能なスペースを、加重比率で分散させることもできます。 これを実行するには、RowDefinition の高さまたは ColumnDefinition の幅を、* 演算子を使用する値に設定します。

注意

Auto サイズに設定する行と列をできるだけ少なくしてください。 自動サイズ調整された行または列はそれぞれ、レイアウト エンジンに追加のレイアウト計算を実行させることになります。 その代わりに可能であれば、固定サイズの行と列を使用してください。 あるいは、GridUnitType.Star 列挙値に比例した量のスペースを占めるように行と列を設定します。

詳細については、「Xamarin.Forms グリッド」を参照してください。

FlexLayout

FlexLayout は、スタック内で水平方向または垂直方向に子要素を表示するという点で StackLayout に似ています。 ただし、FlexLayout は、子が多すぎて 1 つの行または列に収まらない場合は、子を折り返すこともできます。また、子要素のサイズ、向き、配置をより細かく制御することもできます。

次の XAML は、ビューを 1 つの列に表示する FlexLayout オブジェクトを作成する方法を示しています。

<FlexLayout Direction="Column"
            AlignItems="Center"
            JustifyContent="SpaceEvenly">
    <Label Text="FlexLayout in Action" />
    <Button Text="Button" />
    <Label Text="Another Label" />
</FlexLayout>

この例では、レイアウトは次のように動作します。

  • Direction プロパティが Column に設定され、その結果、FlexLayout の子が 1 列の項目に配置されます。
  • AlignItems プロパティが Center に設定されている場合、各項目は水平方向に中央揃えになります。
  • JustifyContent プロパティが SpaceEvenly に設定され、その結果、すべての項目の間、最初の項目の上、最後の項目の下に、残りの垂直スペースがすべて均等に配分されます。

詳細については、「Xamarin.Forms FlexLayout」を参照してください。

RelativeLayout

RelativeLayout は、レイアウトまたは兄弟要素のプロパティを基準にして要素を配置およびサイズ設定するために使用されます。 既定では、要素はレイアウトの左上隅に配置されます。 RelativeLayout を使うと、デバイスのサイズに比例して拡大縮小する UI を作成できます。

RelativeLayout 内では、制約として位置とサイズが指定されます。 制約には Factor および Constant プロパティがあります。これらを使うと、他のオブジェクトのプロパティの倍数 (または分数) に定数を加えたものとして位置とサイズを定義できます。 さらに、定数には負の値を指定できます。

Note

RelativeLayout では、それ自体の境界外に要素を配置できます。

次の XAML は、RelativeLayout 内で要素を配置する方法を示しています。

<RelativeLayout>
    <BoxView Color="Blue"
             HeightRequest="50"
             WidthRequest="50"
             RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0}"
             RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0}" />
    <BoxView Color="Red"
             HeightRequest="50"
             WidthRequest="50"
             RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=.85}"
             RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0}" />
    <BoxView x:Name="pole"
             Color="Gray"
             WidthRequest="15"
             RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=.75}"
             RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=.45}"
             RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=.25}" />
    <BoxView Color="Green"
             RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=.10, Constant=10}"
             RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=.2, Constant=20}"
             RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToView, ElementName=pole, Property=X, Constant=15}"
             RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToView, ElementName=pole, Property=Y, Constant=0}" />
</RelativeLayout>

この例では、レイアウトは次のように動作します。

  • 青色の BoxView には、デバイスに依存しない 50 x 50 単位の明示的なサイズが指定されています。 これは、既定の位置であるレイアウトの左上隅に配置されます。
  • 赤色の BoxView には、デバイスに依存しない 50 x 50 単位の明示的なサイズが指定されています。 これは、レイアウトの右上隅に配置されます。
  • 灰色の BoxView には、デバイスに依存しない 15 単位の明示的な幅が指定され、その高さは親の高さの 75% に設定されます。
  • 緑色の BoxView には明示的なサイズが指定されていません。 その位置は、pole という BoxView に対して相対的に設定されます。

警告

可能であれば、RelativeLayout は使用しないでください。 CPU で相当な量の作業を実行しなければならなくなります。

詳細については、「Xamarin.Forms RelativeLayout」を参照してください。

AbsoluteLayout

AbsoluteLayout は、明示的な値やレイアウトのサイズを基準とした値を使用して、要素の位置およびサイズ変更をするために使用されます。 位置は、AbsoluteLayout の左上隅を基準とする子の左上隅の位置によって指定されます。

AbsoluteLayout は、子のサイズを設定できる場合、または要素のサイズが他の子の位置に影響を与えない場合に限り、特別な目的のレイアウトの用途向けとする必要があります。 このレイアウトの標準的な使用法は、ページを他のコントロールで覆うオーバーレイを作成して、おそらくは、ページ上の通常のコントロールをユーザーが対話的操作できないようにすることです。

重要

HorizontalOptions プロパティと VerticalOptions プロパティは、AbsoluteLayout の子には影響しません。

AbsoluteLayout 内では、AbsoluteLayout.LayoutBounds 添付プロパティを使用して、要素の水平方向の位置、垂直方向の位置、幅、高さを指定します。 さらに、AbsoluteLayout.LayoutFlags 添付プロパティは、レイアウト境界の解釈方法を指定します。

次の XAML は、AbsoluteLayout で要素を配置する方法を示しています。

<AbsoluteLayout Margin="40">
    <BoxView Color="Red"
             AbsoluteLayout.LayoutFlags="PositionProportional"
             AbsoluteLayout.LayoutBounds="0.5, 0, 100, 100"
             Rotation="30" />
    <BoxView Color="Green"
             AbsoluteLayout.LayoutFlags="PositionProportional"
             AbsoluteLayout.LayoutBounds="0.5, 0, 100, 100"
             Rotation="60" />
    <BoxView Color="Blue"
             AbsoluteLayout.LayoutFlags="PositionProportional"
             AbsoluteLayout.LayoutBounds="0.5, 0, 100, 100" />
</AbsoluteLayout>

この例では、レイアウトは次のように動作します。

  • BoxView には 100 x 100 の明示的なサイズが指定され、同じ位置に水平方向の中央揃えで表示されます。
  • BoxView は 30 度回転し、緑 BoxView は 60 度回転します。
  • BoxView で、AbsoluteLayout.LayoutFlags 添付プロパティが PositionProportional に設定されている場合、幅と高さが考慮された後の残りの空間に比例する位置であることを示します。

注意

AbsoluteLayout.AutoSize プロパティを使用すると、レイアウト エンジンが追加のレイアウト計算を行うことになるため、可能な限り使用を避けてください。

詳細については、「Xamarin.Forms AbsoluteLayout」を参照してください。

入力透明性

各ビジュアル要素には、要素が入力を受け取るかどうかを定義するために使われる InputTransparent プロパティがあります。 その既定値は false であり、要素は入力を受け取ります。

このプロパティがレイアウト クラスに設定されている場合、その値は子要素に転送されます。 そのため、レイアウト クラスで InputTransparent プロパティを true に設定すると、レイアウト内のすべての要素が入力を受け取りません。

レイアウト パフォーマンス

可能な限り最適なレイアウト パフォーマンスを得るために、「レイアウトのパフォーマンスを最適化する」のガイドラインに従ってください。

さらに、ビジュアル ツリーから指定されたレイアウトを削除するレイアウト圧縮を使うことによって、ページ レンダリングのパフォーマンスを向上させることもできます。 詳細については、「レイアウトの圧縮」を参照してください。