Xamarin.FormsCollectionView のレイアウト

Download Sampleサンプルのダウンロード

CollectionView は、レイアウトを制御する次のプロパティを定義します:

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

既定では、CollectionView は項目を縦向きリストで表示します。 ただし、次のいずれかのレイアウトも使用できます。

  • 縦向きリスト – 新しい項目が追加されると縦に広がる 1 列のリスト。
  • 横向きリスト – 新しい項目が追加されると横に広がる 1 行のリスト。
  • 縦向きグリッド – 新しい項目が追加されると縦に広がる複数列のグリッド。
  • 横向きグリッド – 新しい項目が追加されると横に広がる複数行のグリッド。

これらのレイアウトは、ItemsLayout プロパティを ItemsLayout クラスから派生するクラスに設定することで指定できます。 このクラスでは、次のプロパティが定義されています。

これらのプロパティはすべて、BindableProperty オブジェクトを基盤としています。つまり、プロパティをデータ バインディングの対象にすることができます。 スナップポイントの詳細については、「Xamarin.FormsCollectionView スクロール ガイド」の「スナップ ポイント」を参照してください。

ItemsLayoutOrientation 列挙型には、次のメンバーが定義されています。

  • Vertical は、項目が追加されると CollectionView が縦に広がることを示します。
  • Horizontal は、項目が追加されると CollectionView が横に広がることを示します。

LinearItemsLayout クラスは ItemsLayout クラスを継承し、各項目の周囲の空のスペースを表す double 型 の ItemSpacing プロパティを定義します。 このプロパティの既定値は 0 であり、その値は常に 0 以上である必要があります。 LinearItemsLayout クラスでは、静的な Vertical メンバーと Horizontal メンバーも定義されます。 これらのメンバーを使用すると、縦向きまたは横向きのリストをそれぞれ作成できます。 または、ItemsLayoutOrientation 列挙メンバーを引数として指定して、LinearItemsLayout オブジェクトを作成することもできます。

GridItemsLayout クラスは ItemsLayout クラスを継承し、次のプロパティを定義します。

  • 各項目の周囲の縦方向の空きスペースを表す、double 型の VerticalItemSpacing。 このプロパティの既定値は 0 であり、その値は常に 0 以上である必要があります。
  • 各項目の周囲の横方向の空きスペースを表す、double 型の HorizontalItemSpacing。 このプロパティの既定値は 0 であり、その値は常に 0 以上である必要があります。
  • グリッドに表示する列数または行数を表す、int 型の Span。 このプロパティの既定値は 1 であり、その値は常に 1 以上である必要があります。

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

Note

CollectionView では、ネイティブ レイアウト エンジンを使用してレイアウトを実行します。

バーティカル リスト

既定では、CollectionView は項目を縦向きリストのレイアウトで表示します。 そのため、そのレイアウトを使用するように ItemsLayout プロパティを設定する必要はありません。

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <Grid Padding="10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
                <Image Grid.RowSpan="2"
                       Source="{Binding ImageUrl}"
                       Aspect="AspectFill"
                       HeightRequest="60"
                       WidthRequest="60" />
                <Label Grid.Column="1"
                       Text="{Binding Name}"
                       FontAttributes="Bold" />
                <Label Grid.Row="1"
                       Grid.Column="1"
                       Text="{Binding Location}"
                       FontAttributes="Italic"
                       VerticalOptions="End" />
            </Grid>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

ただし、完全を期すために、XAML で ItemsLayout プロパティを VerticalList に設定することで、項目を縦向きリストに表示するように CollectionView を設定することもできます。

<CollectionView ItemsSource="{Binding Monkeys}"
                ItemsLayout="VerticalList">
    ...
</CollectionView>

または、VerticalItemsLayoutOrientation 列挙メンバーを Orientation プロパティ値として指定し、ItemsLayout プロパティを LinearItemsLayout オブジェクトに設定することで、これを実現することもできます。

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemsLayout>
        <LinearItemsLayout Orientation="Vertical" />
    </CollectionView.ItemsLayout>
    ...
</CollectionView>

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

CollectionView collectionView = new CollectionView
{
    ...
    ItemsLayout = LinearItemsLayout.Vertical
};

これにより、新しい項目が追加されると縦に広がる、1 列のリストが作成されます。

Screenshot of a CollectionView vertical list layout, on iOS and Android

横向きリスト

XAML で ItemsLayout プロパティを HorizontalList に設定することで、CollectionView で項目を横向きリストに表示できます。

<CollectionView ItemsSource="{Binding Monkeys}"
                ItemsLayout="HorizontalList">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <Grid Padding="10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="35" />
                    <RowDefinition Height="35" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="70" />
                    <ColumnDefinition Width="140" />
                </Grid.ColumnDefinitions>
                <Image Grid.RowSpan="2"
                       Source="{Binding ImageUrl}"
                       Aspect="AspectFill"
                       HeightRequest="60"
                       WidthRequest="60" />
                <Label Grid.Column="1"
                       Text="{Binding Name}"
                       FontAttributes="Bold"
                       LineBreakMode="TailTruncation" />
                <Label Grid.Row="1"
                       Grid.Column="1"
                       Text="{Binding Location}"
                       LineBreakMode="TailTruncation"
                       FontAttributes="Italic"
                       VerticalOptions="End" />
            </Grid>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

または、HorizontalItemsLayoutOrientation 列挙メンバーを Orientation プロパティ値として指定し、ItemsLayout プロパティを LinearItemsLayout オブジェクトに設定することで、このレイアウトを実現することもできます。

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemsLayout>
        <LinearItemsLayout Orientation="Horizontal" />
    </CollectionView.ItemsLayout>
    ...
</CollectionView>

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

CollectionView collectionView = new CollectionView
{
    ...
    ItemsLayout = LinearItemsLayout.Horizontal
};

これにより、新しい項目が追加されると横に広がる、1 行リストが作成されます。

Screenshot of a CollectionView horizontal list layout, on iOS and Android

垂直グリッド

XAML で ItemsLayout プロパティを VerticalGrid に設定することで、CollectionView で項目を縦向きグリッドに表示できます。

<CollectionView ItemsSource="{Binding Monkeys}"
                ItemsLayout="VerticalGrid, 2">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <Grid Padding="10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="35" />
                    <RowDefinition Height="35" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="70" />
                    <ColumnDefinition Width="80" />
                </Grid.ColumnDefinitions>
                <Image Grid.RowSpan="2"
                       Source="{Binding ImageUrl}"
                       Aspect="AspectFill"
                       HeightRequest="60"
                       WidthRequest="60" />
                <Label Grid.Column="1"
                       Text="{Binding Name}"
                       FontAttributes="Bold"
                       LineBreakMode="TailTruncation" />
                <Label Grid.Row="1"
                       Grid.Column="1"
                       Text="{Binding Location}"
                       LineBreakMode="TailTruncation"
                       FontAttributes="Italic"
                       VerticalOptions="End" />
            </Grid>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

または、Orientation プロパティが Vertical に設定されている GridItemsLayout オブジェクトに ItemsLayout プロパティを設定することで、このレイアウトを実現することもできます。

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemsLayout>
       <GridItemsLayout Orientation="Vertical"
                        Span="2" />
    </CollectionView.ItemsLayout>
    ...
</CollectionView>

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

CollectionView collectionView = new CollectionView
{
    ...
    ItemsLayout = new GridItemsLayout(2, ItemsLayoutOrientation.Vertical)
};

既定では、縦向き GridItemsLayout の項目は 1 列に表示されます。 この例では、GridItemsLayout.Span プロパティを 2 に設定しています。 これにより、2 列のグリッドが作成され、新しい項目が追加されると縦に広がります。

Screenshot of a CollectionView vertical grid layout, on iOS and Android

水平グリッド

XAML で ItemsLayout プロパティを HorizontalGrid に設定することで、CollectionView で項目を横向きグリッドに表示できます。

<CollectionView ItemsSource="{Binding Monkeys}"
                ItemsLayout="HorizontalGrid, 4">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <Grid Padding="10">
                <Grid.RowDefinitions>
                    <RowDefinition Height="35" />
                    <RowDefinition Height="35" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="70" />
                    <ColumnDefinition Width="140" />
                </Grid.ColumnDefinitions>
                <Image Grid.RowSpan="2"
                       Source="{Binding ImageUrl}"
                       Aspect="AspectFill"
                       HeightRequest="60"
                       WidthRequest="60" />
                <Label Grid.Column="1"
                       Text="{Binding Name}"
                       FontAttributes="Bold"
                       LineBreakMode="TailTruncation" />
                <Label Grid.Row="1"
                       Grid.Column="1"
                       Text="{Binding Location}"
                       LineBreakMode="TailTruncation"
                       FontAttributes="Italic"
                       VerticalOptions="End" />
            </Grid>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

または、Orientation プロパティが Horizontal に設定されている GridItemsLayout オブジェクトに ItemsLayout プロパティを設定することで、このレイアウトを実現することもできます。

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemsLayout>
       <GridItemsLayout Orientation="Horizontal"
                        Span="4" />
    </CollectionView.ItemsLayout>
    ...
</CollectionView>

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

CollectionView collectionView = new CollectionView
{
    ...
    ItemsLayout = new GridItemsLayout(4, ItemsLayoutOrientation.Horizontal)
};

既定では、横向き GridItemsLayout の項目は 1 行に表示されます。 この例では、GridItemsLayout.Span プロパティを 4 に設定しています。 これにより、4 行のグリッドが作成され、新しい項目が追加されると横に広がります。

Screenshot of a CollectionView horizontal grid layout, on iOS and Android

ヘッダーとフッター

CollectionView では、リスト内の項目と共にスクロールするヘッダーとフッターを表示できます。 ヘッダーとフッターには、文字列、ビュー、DataTemplate オブジェクトを指定できます。

CollectionView は、ヘッダーとフッターを指定するための次のプロパティを定義します。

  • object 型の Header は、リストの先頭に表示される文字列、バインド、またはビューを指定します。
  • DataTemplate 型の HeaderTemplate は、Header の書式を設定するために使用する DataTemplate を指定します。
  • object 型の Footer は、リストの末尾に表示される文字列、バインド、またはビューを指定します。
  • DataTemplate 型の FooterTemplate は、Footer の書式を設定するために使用する DataTemplate を指定します。

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

左から右へ横に広がるレイアウトにヘッダーを追加すると、ヘッダーはリストの左側に表示されます。 同様に、左から右へ横に広がるレイアウトにフッターを追加すると、フッターはリストの右側に表示されます。

次の例に示すように、Header プロパティと Footer プロパティは、string 値に設定することもできます。

<CollectionView ItemsSource="{Binding Monkeys}"
                Header="Monkeys"
                Footer="2019">
    ...
</CollectionView>

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

CollectionView collectionView = new CollectionView
{
    Header = "Monkeys",
    Footer = "2019"
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");

このコードの結果は次のスクリーンショットのようになり、ヘッダーは iOS のスクリーンショットに、フッターは Android のスクリーンショットに表示されます。

Screenshot of a CollectionView string header and footer, on iOS and Android

Header プロパティと Footer プロパティには、それぞれビューを設定できます。 1 つのビュー、または複数の子ビューを含むビューを指定できます。 次の例は、Header プロパティと Footer プロパティがそれぞれ、Label オブジェクトを含む StackLayout オブジェクトに設定されていることを示しています。

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.Header>
        <StackLayout BackgroundColor="LightGray">
            <Label Margin="10,0,0,0"
                   Text="Monkeys"
                   FontSize="Small"
                   FontAttributes="Bold" />
        </StackLayout>
    </CollectionView.Header>
    <CollectionView.Footer>
        <StackLayout BackgroundColor="LightGray">
            <Label Margin="10,0,0,0"
                   Text="Friends of Xamarin Monkey"
                   FontSize="Small"
                   FontAttributes="Bold" />
        </StackLayout>
    </CollectionView.Footer>
    ...
</CollectionView>

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

CollectionView collectionView = new CollectionView
{
    Header = new StackLayout
    {
        Children =
        {
            new Label { Text = "Monkeys", ... }
        }
    },
    Footer = new StackLayout
    {
        Children =
        {
            new Label { Text = "Friends of Xamarin Monkey", ... }
        }
    }
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");

このコードの結果は次のスクリーンショットのようになり、ヘッダーは iOS のスクリーンショットに、フッターは Android のスクリーンショットに表示されます。

Screenshot of a CollectionView header and footer using views, on iOS and Android

HeaderTemplate プロパティと FooterTemplate プロパティを DataTemplate オブジェクトに設定すると、ヘッダーとフッターの書式設定に使用できます。 このシナリオでは、以下の例に示すように、テンプレートを適用するためには、Header プロパティと Footer プロパティが現在のソースにバインドされている必要があります。

<CollectionView ItemsSource="{Binding Monkeys}"
                Header="{Binding .}"
                Footer="{Binding .}">
    <CollectionView.HeaderTemplate>
        <DataTemplate>
            <StackLayout BackgroundColor="LightGray">
                <Label Margin="10,0,0,0"
                       Text="Monkeys"
                       FontSize="Small"
                       FontAttributes="Bold" />
            </StackLayout>
        </DataTemplate>
    </CollectionView.HeaderTemplate>
    <CollectionView.FooterTemplate>
        <DataTemplate>
            <StackLayout BackgroundColor="LightGray">
                <Label Margin="10,0,0,0"
                       Text="Friends of Xamarin Monkey"
                       FontSize="Small"
                       FontAttributes="Bold" />
            </StackLayout>
        </DataTemplate>
    </CollectionView.FooterTemplate>
    ...
</CollectionView>

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

CollectionView collectionView = new CollectionView
{
    HeaderTemplate = new DataTemplate(() =>
    {
        return new StackLayout { };
    }),
    FooterTemplate = new DataTemplate(() =>
    {
        return new StackLayout { };
    })
};
collectionView.SetBinding(ItemsView.HeaderProperty, ".");
collectionView.SetBinding(ItemsView.FooterProperty, ".");
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");

このコードの結果は次のスクリーンショットのようになり、ヘッダーは iOS のスクリーンショットに、フッターは Android のスクリーンショットに表示されます。

Screenshot of a CollectionView header and footer using templates, on iOS and Android

項目の間隔

既定では、CollectionView 内の各項目の間にスペースはありません。 この動作は、CollectionView で使用される項目レイアウトのプロパティを設定することで変更できます。

CollectionView でその ItemsLayout プロパティを LinearItemsLayout オブジェクトに設定すると、項目間のスペースを表す double 値を LinearItemsLayout.ItemSpacing プロパティに設定できます。

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemsLayout>
        <LinearItemsLayout Orientation="Vertical"
                           ItemSpacing="20" />
    </CollectionView.ItemsLayout>
    ...
</CollectionView>

Note

LinearItemsLayout.ItemSpacing プロパティには、プロパティの値が常に 0 以上であることを確認できる、検証コールバック セットがあります。

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

CollectionView collectionView = new CollectionView
{
    ...
    ItemsLayout = new LinearItemsLayout(ItemsLayoutOrientation.Vertical)
    {
        ItemSpacing = 20
    }
};

このコードでは、項目間の間隔が 20 の垂直方向の縦 1 列のいリストになります:

Screenshot of a CollectionView with item spacing, on iOS and Android

CollectionViewItemsLayout プロパティを GridItemsLayout オブジェクトに設定すると、項目間の縦と横の空きスペースを表す double 値を GridItemsLayout.VerticalItemSpacing プロパティと GridItemsLayout.HorizontalItemSpacing プロパティに設定できます。

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemsLayout>
       <GridItemsLayout Orientation="Vertical"
                        Span="2"
                        VerticalItemSpacing="20"
                        HorizontalItemSpacing="30" />
    </CollectionView.ItemsLayout>
    ...
</CollectionView>

Note

GridItemsLayout.VerticalItemSpacing プロパティと GridItemsLayout.HorizontalItemSpacing プロパティには検証コールバックが設定されており、プロパティの値が常に 0 以上であることを確認します。

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

CollectionView collectionView = new CollectionView
{
    ...
    ItemsLayout = new GridItemsLayout(2, ItemsLayoutOrientation.Vertical)
    {
        VerticalItemSpacing = 20,
        HorizontalItemSpacing = 30
    }
};

このコードにより、項目間の縦方向の間隔が 20、項目間の水平方向の間隔が 30 の縦 2 列のグリッドが作成されます:

Screenshot of a CollectionView with item spacing, on Android

項目のサイズ

既定では、DataTemplate の UI 要素が固定サイズを指定されていない限り、CollectionView の各項目は個別に測定され、サイズが設定されます。 この動作は変更でき、CollectionView.ItemSizingStrategy プロパティ値で指定できます。 このプロパティの値は、ItemSizingStrategy 列挙要素に 1 つに設定されます。

  • MeasureAllItems – 各項目は個別に測定されます。 これが既定値です。
  • MeasureFirstItem – 最初の項目のみが測定され、後続のすべての項目に最初の項目と同じサイズが与えられます。

重要

MeasureFirstItem の方法でサイズを設定すると、項目のサイズがすべての項目で均一な状況でパフォーマンスが向上します。

次のコード例では、ItemSizingStrategy プロパティの設定を示します。

<CollectionView ...
                ItemSizingStrategy="MeasureFirstItem">
    ...
</CollectionView>

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

CollectionView collectionView = new CollectionView
{
    ...
    ItemSizingStrategy = ItemSizingStrategy.MeasureFirstItem
};

項目の動的なサイズ変更

DataTemplate 内の要素の レイアウト関連プロパティを変更することで、CollectionView の項目のサイズを実行時に動的に変更できます。 たとえば、次のコード例では、Image オブジェクトの HeightRequest プロパティと WidthRequest プロパティを変更します。

void OnImageTapped(object sender, EventArgs e)
{
    Image image = sender as Image;
    image.HeightRequest = image.WidthRequest = image.HeightRequest.Equals(60) ? 100 : 60;
}

OnImageTapped イベント ハンドラーはタップされている Image オブジェクトに応答して実行され、画像のサイズを変更して表示しやすくします。

Screenshot of a CollectionView with dynamic item sizing, on iOS and Android

右から左へのレイアウト

CollectionView を使用すると、FlowDirection プロパティを RightToLeft に設定することで、コンテンツを右から左へのフロー方向にレイアウトできます。 ただし、FlowDirection プロパティは、ページまたはルート レイアウトに設定するのが理想的です。これにより、そのページまたはルート レイアウト内のすべての要素について、フローの方向が定まります。

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="CollectionViewDemos.Views.VerticalListFlowDirectionPage"
             Title="Vertical list (RTL FlowDirection)"
             FlowDirection="RightToLeft">
    <StackLayout Margin="20">
        <CollectionView ItemsSource="{Binding Monkeys}">
            ...
        </CollectionView>
    </StackLayout>
</ContentPage>

親を持つ要素の既定の FlowDirectionMatchParent です。 そのため、CollectionViewStackLayout から FlowDirection プロパティ値を継承し、さらに ContentPage から FlowDirection プロパティ値を継承します。 これで、次のスクリーンショットに示すような右から左のレイアウトになります:

Screenshot of a CollectionView right-to-left vertical list layout, on iOS and Android

フローの向きについて詳しくは、「右から左へのローカライズ」をご覧ください。