Xamarin.Forms StackLayout

Xamarin.Forms StackLayout

StackLayout は、子ビューを水平方向または垂直方向の 1 次元のスタックに編成します。 既定では、StackLayout は垂直方向に配置されます。 さらに StackLayout は、他の子レイアウトを含む親レイアウトとして使用できます。

StackLayout クラスには、次のプロパティが定義されています。

  • Orientation (StackOrientation 型): 子ビューが配置される方向を表します。 このプロパティの既定値は Vertical です。
  • double 型 の Spacing は、各子ビュー間のスペースの量を示します。 このプロパティの既定値は、デバイスに依存しない 6 単位です。

これらのプロパティは、BindableProperty オブジェクトがサポートしています。つまり、プロパティをデータ バインディングの対象にして、スタイル設定することができます。

StackLayout クラスは、IList<T> 型の Children プロパティを定義する Layout<T> クラスから派生します。 Children プロパティは Layout<T> クラスの ContentProperty であるため、XAML から明示的に設定する必要はありません。

ヒント

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

垂直方向

次の XAML は、さまざまな子ビューを含んだ垂直方向の StackLayout を作成する方法を示しています。

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="StackLayoutDemos.Views.VerticalStackLayoutPage"
             Title="Vertical StackLayout demo">
    <StackLayout Margin="20">
        <Label Text="Primary colors" />
        <BoxView Color="Red" />
        <BoxView Color="Yellow" />
        <BoxView Color="Blue" />
        <Label Text="Secondary colors" />
        <BoxView Color="Green" />
        <BoxView Color="Orange" />
        <BoxView Color="Purple" />
    </StackLayout>
</ContentPage>

この例では、Label オブジェクトと BoxView オブジェクトを含んだ垂直方向の StackLayout を作成します。 既定では、子ビュー間には、デバイスに依存しない 6 単位のスペースがあります。

垂直方向の StackLayout のスクリーンショット

同等の C# コードを次に示します。

public class VerticalStackLayoutPageCS : ContentPage
{
    public VerticalStackLayoutPageCS()
    {
        Title = "Vertical StackLayout demo";
        Content = new StackLayout
        {
            Margin = new Thickness(20),
            Children =
            {
                new Label { Text = "Primary colors" },
                new BoxView { Color = Color.Red },
                new BoxView { Color = Color.Yellow },
                new BoxView { Color = Color.Blue },
                new Label { Text = "Secondary colors" },
                new BoxView { Color = Color.Green },
                new BoxView { Color = Color.Orange },
                new BoxView { Color = Color.Purple }
            }
        };
    }
}

Note

Margin プロパティの値は、要素とその隣接する要素の間の距離を表します。 詳細については「Margin and Padding」 (余白とスペース) を参照してください。

水平方向

次の XAML は、Orientation プロパティを Horizontal に設定して水平方向の StackLayout を作成する方法を示しています。

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="StackLayoutDemos.Views.HorizontalStackLayoutPage"
             Title="Horizontal StackLayout demo">
    <StackLayout Margin="20"
                 Orientation="Horizontal"
                 HorizontalOptions="Center">
        <BoxView Color="Red" />
        <BoxView Color="Yellow" />
        <BoxView Color="Blue" />
        <BoxView Color="Green" />
        <BoxView Color="Orange" />
        <BoxView Color="Purple" />
    </StackLayout>
</ContentPage>

この例では、子ビュー間にデバイスに依存しない 6 単位のスペースを持つ、BoxView オブジェクトを含む水平方向の StackLayout を作成します。

水平方向の StackLayout のスクリーンショット

同等の C# コードを次に示します。

public HorizontalStackLayoutPageCS()
{
    Title = "Horizontal StackLayout demo";
    Content = new StackLayout
    {
        Margin = new Thickness(20),
        Orientation = StackOrientation.Horizontal,
        HorizontalOptions = LayoutOptions.Center,
        Children =
        {
            new BoxView { Color = Color.Red },
            new BoxView { Color = Color.Yellow },
            new BoxView { Color = Color.Blue },
            new BoxView { Color = Color.Green },
            new BoxView { Color = Color.Orange },
            new BoxView { Color = Color.Purple }
        }
    };
}

子ビュー間のスペース

Spacing プロパティを double 値に設定すると、StackLayout 内の子ビュー間の間隔を変更できます。

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="StackLayoutDemos.Views.StackLayoutSpacingPage"
             Title="StackLayout Spacing demo">
    <StackLayout Margin="20"
                 Spacing="0">
        <Label Text="Primary colors" />
        <BoxView Color="Red" />
        <BoxView Color="Yellow" />
        <BoxView Color="Blue" />
        <Label Text="Secondary colors" />
        <BoxView Color="Green" />
        <BoxView Color="Orange" />
        <BoxView Color="Purple" />
    </StackLayout>
</ContentPage>

この例では、間にスペースのない Label オブジェクトと BoxView オブジェクトを含む垂直方向の StackLayout を作成します。

間にスペースがない StackLayout のスクリーンショット

ヒント

Spacing のプロパティを負の値に設定し、子ビューを重ね合わせることができます。

同等の C# コードを次に示します。

public class StackLayoutSpacingPageCS : ContentPage
{
    public StackLayoutSpacingPageCS()
    {
        Title = "StackLayout Spacing demo";
        Content = new StackLayout
        {
            Margin = new Thickness(20),
            Spacing = 0,
            Children =
            {
                new Label { Text = "Primary colors" },
                new BoxView { Color = Color.Red },
                new BoxView { Color = Color.Yellow },
                new BoxView { Color = Color.Blue },
                new Label { Text = "Secondary colors" },
                new BoxView { Color = Color.Green },
                new BoxView { Color = Color.Orange },
                new BoxView { Color = Color.Purple }
            }
        };
    }
}

子ビューの位置とサイズ

StackLayout 内の子ビューのサイズと位置は、子ビューの HeightRequest プロパティと WidthRequest プロパティの値、および HorizontalOptions プロパティと VerticalOptions プロパティの値によって異なります。 垂直方向の StackLayout では、サイズが明示的に設定されていない場合、子ビューは使用可能な幅に合わせて広がります。 同様に、水平方向の StackLayout では、サイズが明示的に設定されていない場合、子ビューは使用可能な高さに合わせて広がります。

StackLayout の HorizontalOptions プロパティと VerticalOptions プロパティ、その子ビューは、2 つのレイアウト設定をカプセル化する LayoutOptions 構造体のフィールドに設定できます。

  • "配置" は、親レイアウト内の子ビューの位置とサイズを設定します。
  • "展開" は、子ビューが、追加のスペースを使用できる場合に、使う必要があるかどうかを示します。

ヒント

必要な場合を除き、StackLayout の HorizontalOptions と VerticalOptions のプロパティを設定しないでください。 既定値の LayoutOptions.Fill と LayoutOptions.FillAndExpand で、レイアウトの最適化が最大になります。 これらのプロパティの変更にはコストがかかり、既定値に戻すように設定する場合でも、メモリを消費します。

Alignment

次の XAML の例では、StackLayout の各子ビューに配置設定を設定します。

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="StackLayoutDemos.Views.AlignmentPage"
             Title="Alignment demo">
    <StackLayout Margin="20">
        <Label Text="Start"
               BackgroundColor="Gray"
               HorizontalOptions="Start" />
        <Label Text="Center"
               BackgroundColor="Gray"
               HorizontalOptions="Center" />
        <Label Text="End"
               BackgroundColor="Gray"
               HorizontalOptions="End" />
        <Label Text="Fill"
               BackgroundColor="Gray"
               HorizontalOptions="Fill" />
    </StackLayout>
</ContentPage>

この例では、Label オブジェクトの配置設定を設定して、StackLayout 内の位置を制御します。 Start、Center、End、Fill の各フィールドは、親 StackLayout 内の Label オブジェクトの配置を定義するために使用されます。

配置オプションが設定されている StackLayout のスクリーンショット

StackLayout は、StackLayout の方向とは反対方向にある子ビューの配置設定のみに従います。 したがって、垂直方向の StackLayout 内の Label 子ビューは、それらの HorizontalOptions プロパティを次の配置フィールドの 1 つに設定します。

同等の C# コードを次に示します。

public class AlignmentPageCS : ContentPage
{
    public AlignmentPageCS()
    {
        Title = "Alignment demo";
        Content = new StackLayout
        {
            Margin = new Thickness(20),
            Children =
            {
                new Label { Text = "Start", BackgroundColor = Color.Gray, HorizontalOptions = LayoutOptions.Start },
                new Label { Text = "Center", BackgroundColor = Color.Gray, HorizontalOptions = LayoutOptions.Center },
                new Label { Text = "End", BackgroundColor = Color.Gray, HorizontalOptions = LayoutOptions.End },
                new Label { Text = "Fill", BackgroundColor = Color.Gray, HorizontalOptions = LayoutOptions.Fill }
            }
        };
    }
}

正規の表記

次の XAML 例では、StackLayout 内の各 Label に展開設定を設定します。

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="StackLayoutDemos.Views.ExpansionPage"
             Title="Expansion demo">
    <StackLayout Margin="20">
        <BoxView BackgroundColor="Red"
                 HeightRequest="1" />
        <Label Text="Start"
               BackgroundColor="Gray"
               VerticalOptions="StartAndExpand" />
        <BoxView BackgroundColor="Red"
                 HeightRequest="1" />
        <Label Text="Center"
               BackgroundColor="Gray"
               VerticalOptions="CenterAndExpand" />
        <BoxView BackgroundColor="Red"
                 HeightRequest="1" />
        <Label Text="End"
               BackgroundColor="Gray"
               VerticalOptions="EndAndExpand" />
        <BoxView BackgroundColor="Red"
                 HeightRequest="1" />
        <Label Text="Fill"
               BackgroundColor="Gray"
               VerticalOptions="FillAndExpand" />
        <BoxView BackgroundColor="Red"
                 HeightRequest="1" />
    </StackLayout>
</ContentPage>

この例では、StackLayout 内でのサイズを制御するために、Label オブジェクトに拡張設定が設定されています。 StartAndExpand、CenterAndExpand、EndAndExpand、FillAndExpand フィールドは、配置設定と、親 StackLayout 内で使用できる場合に Label がより多くのスペースを占有するかどうかを定義するために使われます。

拡張オプションが設定されている StackLayout のスクリーンショット

StackLayout は子ビューをその方向にのみ展開できます。 したがって、垂直方向の StackLayout は、VerticalOptions プロパティをいずれかの展開フィールドに設定する Label 子ビューを展開できます。 つまり、垂直方向の配置では、各 Label が StackLayout 内で同じ量のスペースを占有します。 ただし、VerticalOptions プロパティを FillAndExpand に設定する最後の Label のみ、サイズが異なります。

ヒント

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

同等の C# コードを次に示します。

public ExpansionPageCS()
{
    Title = "Expansion demo";
    Content = new StackLayout
    {
        Margin = new Thickness(20),
        Children =
        {
            new BoxView { BackgroundColor = Color.Red, HeightRequest = 1 },
            new Label { Text = "StartAndExpand", BackgroundColor = Color.Gray, VerticalOptions = LayoutOptions.StartAndExpand },
            new BoxView { BackgroundColor = Color.Red, HeightRequest = 1 },
            new Label { Text = "CenterAndExpand", BackgroundColor = Color.Gray, VerticalOptions = LayoutOptions.CenterAndExpand },
            new BoxView { BackgroundColor = Color.Red, HeightRequest = 1 },
            new Label { Text = "EndAndExpand", BackgroundColor = Color.Gray, VerticalOptions = LayoutOptions.EndAndExpand },
            new BoxView { BackgroundColor = Color.Red, HeightRequest = 1 },
            new Label { Text = "FillAndExpand", BackgroundColor = Color.Gray, VerticalOptions = LayoutOptions.FillAndExpand },
            new BoxView { BackgroundColor = Color.Red, HeightRequest = 1 }
        }
    };
}

重要

StackLayout 内のすべてのスペースが使用されている場合、展開設定は無効になります。

配置と展開の詳細については、「Xamarin.Forms のレイアウト オプション」を参照してください。

入れ子になった StackLayout オブジェクト

StackLayout は、入れ子になった子 StackLayout オブジェクトまたはその他の子レイアウトを含んだ親レイアウトとして使用できます。

次の XAML は、入れ子になった StackLayout オブジェクトの例を示しています。

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="StackLayoutDemos.Views.CombinedStackLayoutPage"
             Title="Combined StackLayouts demo">
    <StackLayout Margin="20">
        ...
        <Frame BorderColor="Black"
               Padding="5">
            <StackLayout Orientation="Horizontal"
                         Spacing="15">
                <BoxView Color="Red" />
                <Label Text="Red"
                       FontSize="Large"
                       VerticalOptions="Center" />
            </StackLayout>
        </Frame>
        <Frame BorderColor="Black"
               Padding="5">
            <StackLayout Orientation="Horizontal"
                         Spacing="15">
                <BoxView Color="Yellow" />
                <Label Text="Yellow"
                       FontSize="Large"
                       VerticalOptions="Center" />
            </StackLayout>
        </Frame>
        <Frame BorderColor="Black"
               Padding="5">
            <StackLayout Orientation="Horizontal"
                         Spacing="15">
                <BoxView Color="Blue" />
                <Label Text="Blue"
                       FontSize="Large"
                       VerticalOptions="Center" />
            </StackLayout>
        </Frame>
        ...
    </StackLayout>
</ContentPage>

この例では、親 StackLayout には、Frame オブジェクト内にネストされた StackLayout オブジェクトが含まれています。 親 StackLayout は垂直方向に配置され、子 StackLayout オブジェクトは水平方向に配置されます。

入れ子になった StackLayout オブジェクトのスクリーンショット

重要

StackLayout オブジェクトやその他のレイアウトを入れ子にするほど、入れ子になったレイアウトがパフォーマンスに影響します。 詳細については、「正しいレイアウトの選択」を参照してください。

同等の C# コードを次に示します。

public class CombinedStackLayoutPageCS : ContentPage
{
    public CombinedStackLayoutPageCS()
    {
        Title = "Combined StackLayouts demo";
        Content = new StackLayout
        {
            Margin = new Thickness(20),
            Children =
            {
                new Label { Text = "Primary colors" },
                new Frame
                {
                    BorderColor = Color.Black,
                    Padding = new Thickness(5),
                    Content = new StackLayout
                    {
                        Orientation = StackOrientation.Horizontal,
                        Spacing = 15,
                        Children =
                        {
                            new BoxView { Color = Color.Red },
                            new Label { Text = "Red", FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)), VerticalOptions = LayoutOptions.Center }
                        }
                    }
                },
                new Frame
                {
                    BorderColor = Color.Black,
                    Padding = new Thickness(5),
                    Content = new StackLayout
                    {
                        Orientation = StackOrientation.Horizontal,
                        Spacing = 15,
                        Children =
                        {
                            new BoxView { Color = Color.Yellow },
                            new Label { Text = "Yellow", FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)), VerticalOptions = LayoutOptions.Center }
                        }
                    }
                },
                new Frame
                {
                    BorderColor = Color.Black,
                    Padding = new Thickness(5),
                    Content = new StackLayout
                    {
                        Orientation = StackOrientation.Horizontal,
                        Spacing = 15,
                        Children =
                        {
                            new BoxView { Color = Color.Blue },
                            new Label { Text = "Blue", FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)), VerticalOptions = LayoutOptions.Center }
                        }
                    }
                },
                // ...
            }
        };
    }
}