Xamarin.FormsCollectionView のレイアウト
CollectionView
は、レイアウトを制御する次のプロパティを定義します:
IItemsLayout
型のItemsLayout
は、使用するレイアウトを指定します。ItemSizingStrategy
型のItemSizingStrategy
は、使用する項目測定法を指定します。
これらのプロパティはすべて、BindableProperty
オブジェクトを基盤としています。つまり、プロパティをデータ バインディングの対象にすることができます。
既定では、CollectionView
は項目を縦向きリストで表示します。 ただし、次のいずれかのレイアウトも使用できます。
- 縦向きリスト – 新しい項目が追加されると縦に広がる 1 列のリスト。
- 横向きリスト – 新しい項目が追加されると横に広がる 1 行のリスト。
- 縦向きグリッド – 新しい項目が追加されると縦に広がる複数列のグリッド。
- 横向きグリッド – 新しい項目が追加されると横に広がる複数行のグリッド。
これらのレイアウトは、ItemsLayout
プロパティを ItemsLayout
クラスから派生するクラスに設定することで指定できます。 このクラスでは、次のプロパティが定義されています。
ItemsLayoutOrientation
型のOrientation
は、項目が追加されたときにCollectionView
が広がる方向を指定します。SnapPointsAlignment
は、SnapPointsAlignment
型で、スナップ ポイントを項目に合わせる方法を指定します。SnapPointsType
は、SnapPointsType
型で、スクロール時のスナップ ポイントの動作を指定します。
これらのプロパティはすべて、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>
または、これは次のように、ItemsLayout
プロパティを LinearItemsLayout
オブジェクトに設定し、Vertical
ItemsLayoutOrientation
列挙メンバーを Orientation
プロパティ値として指定することでも実現できます。
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Vertical" />
</CollectionView.ItemsLayout>
...
</CollectionView>
同等の C# コードを次に示します。
CollectionView collectionView = new CollectionView
{
...
ItemsLayout = LinearItemsLayout.Vertical
};
これにより、新しい項目が追加されると縦に広がる、1 列のリストが作成されます。
横向きリスト
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>
または次のように、ItemsLayout
プロパティを LinearItemsLayout
オブジェクトに設定し、Horizontal
ItemsLayoutOrientation
列挙メンバーを Orientation
プロパティ値として指定することでも、このレイアウトを実現できます。
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal" />
</CollectionView.ItemsLayout>
...
</CollectionView>
同等の C# コードを次に示します。
CollectionView collectionView = new CollectionView
{
...
ItemsLayout = LinearItemsLayout.Horizontal
};
これにより、新しい項目が追加されると横に広がる、1 行リストが作成されます。
垂直グリッド
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 列のグリッドが作成され、新しい項目が追加されると縦に広がります。
水平グリッド
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 行のグリッドが作成され、新しい項目が追加されると横に広がります。
ヘッダーとフッター
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 のスクリーンショットに表示されます。
ヘッダーとフッターにビューを表示する
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 のスクリーンショットに表示されます。
テンプレート化されたヘッダーとフッターを表示する
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 のスクリーンショットに表示されます。
項目の間隔
既定では、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 列のいリストになります:
CollectionView
で ItemsLayout
プロパティを 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 列のグリッドが作成されます:
項目のサイズ
既定では、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
オブジェクトに応答して実行され、画像のサイズを変更して表示しやすくします。
右から左へのレイアウト
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>
親を持つ要素の既定の FlowDirection
は MatchParent
です。 そのため、CollectionView
は StackLayout
から FlowDirection
プロパティ値を継承し、さらに ContentPage
から FlowDirection
プロパティ値を継承します。 これで、次のスクリーンショットに示すような右から左のレイアウトになります:
フローの向きについて詳しくは、「右から左へのローカライズ」をご覧ください。