Xamarin.Forms CollectionView Layout

Download Sample Download the sample

CollectionView defines the following properties that control layout:

These properties are backed by BindableProperty objects, which means that the properties can be targets of data bindings.

By default, a CollectionView will display its items in a vertical list. However, any of the following layouts can be used:

  • Vertical list – a single column list that grows vertically as new items are added.
  • Horizontal list – a single row list that grows horizontally as new items are added.
  • Vertical grid – a multi-column grid that grows vertically as new items are added.
  • Horizontal grid – a multi-row grid that grows horizontally as new items are added.

These layouts can be specified by setting the ItemsLayout property to class that derives from the ItemsLayout class. This class defines the following properties:

These properties are backed by BindableProperty objects, which means that the properties can be targets of data bindings. For more information about snap points, see Snap points in the Xamarin.Forms CollectionView Scrolling guide.

The ItemsLayoutOrientation enumeration defines the following members:

  • Vertical indicates that the CollectionView will expand vertically as items are added.
  • Horizontal indicates that the CollectionView will expand horizontally as items are added.

The ListItemsLayout class inherits from the ItemsLayout class, and defines an ItemSpacing property, of type double, that represents the empty space around each item. The default value of this property is 0, and its value must always be greater than or equal to 0. The ListItemsLayout class also defines static Vertical and Horizontal members. These members can be used to create vertical or horizontal lists, respectively. Alternatively, a ListItemsLayout object can be created, specifying an ItemsLayoutOrientation enumeration member as an argument.

The GridItemsLayout class inherits from the ItemsLayout class, and defines the following properties:

  • VerticalItemSpacing, of type double, that represents the vertical empty space around each item. The default value of this property is 0, and its value must always be greater than or equal to 0.
  • HorizontalItemSpacing, of type double, that represents the horizontal empty space around each item. The default value of this property is 0, and its value must always be greater than or equal to 0.
  • Span, of type int, that represents the number of columns or rows to display in the grid. The default value of this property is 1, and its value must always be greater than or equal to 1.

These properties are backed by BindableProperty objects, which means that the properties can be targets of data bindings.

Note

CollectionView uses the native layout engines to perform layout.

Vertical list

By default, CollectionView will display its items in a vertical list layout. Therefore, it's not necessary to set the ItemsLayout property to use this layout:

<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>

However, for completeness, a CollectionView can be set to display its items in a vertical list by setting its ItemsLayout property to VerticalList:

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

Alternatively, this can also be accomplished by setting the ItemsLayout property to an object of the ListItemsLayout class, specifying the Vertical ItemsLayoutOrientation enumeration member as an argument:

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemsLayout>
        <ListItemsLayout>
            <x:Arguments>
                <ItemsLayoutOrientation>Vertical</ItemsLayoutOrientation>    
            </x:Arguments>
        </ListItemsLayout>
    </CollectionView.ItemsLayout>
    ...
</CollectionView>

The equivalent C# code is:

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

This results in a single column list, which grows vertically as new items are added:

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

Horizontal list

CollectionView can display its items in a horizontal list by setting its ItemsLayout property to HorizontalList:

<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>

Alternatively, this can also be accomplished by setting the ItemsLayout property to a ListItemsLayout object, specifying the Horizontal ItemsLayoutOrientation enumeration member as an argument:

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemsLayout>
        <ListItemsLayout>
            <x:Arguments>
                <ItemsLayoutOrientation>Horizontal</ItemsLayoutOrientation>    
            </x:Arguments>
        </ListItemsLayout>
    </CollectionView.ItemsLayout>
    ...
</CollectionView>

The equivalent C# code is:

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

This results in a single row list, which grows horizontally as new items are added:

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

Vertical grid

CollectionView can display its items in a vertical grid by setting its ItemsLayout property to a GridItemsLayout object whose Orientation property is set to Vertical:

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemsLayout>
       <GridItemsLayout Orientation="Vertical"
                        Span="2" />
    </CollectionView.ItemsLayout>
    <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>

The equivalent C# code is:

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

By default, a vertical GridItemsLayout will display items in a single column. However, this example sets the GridItemsLayout.Span property to 2. This results in a two-column grid, which grows vertically as new items are added:

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

Horizontal grid

CollectionView can display its items in a horizontal grid by setting its ItemsLayout property to a GridItemsLayout object whoseOrientation property is set to Horizontal:

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemsLayout>
       <GridItemsLayout Orientation="Horizontal"
                        Span="4" />
    </CollectionView.ItemsLayout>
    <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>

The equivalent C# code is:

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

By default, a horizontal GridItemsLayout will display items in a single row. However, this example sets the GridItemsLayout.Span property to 4. This results in a four-row grid, which grows horizontally as new items are added:

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

Item spacing

By default, each item in a CollectionView doesn't have any empty space around it. This behavior can be changed by setting properties on the items layout used by the CollectionView.

When a CollectionView sets its ItemsLayout property to a ListItemsLayout object, the ListItemsLayout.ItemSpacing property can be set to a double value that represents the empty space around each item:

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemsLayout>
        <ListItemsLayout ItemSpacing="20">
            <x:Arguments>
                <ItemsLayoutOrientation>Vertical</ItemsLayoutOrientation>    
            </x:Arguments>
        </ListItemsLayout>
    </CollectionView.ItemsLayout>
    ...
</CollectionView>

Note

The ListItemsLayout.ItemSpacing property has a validation callback set, which ensures that the value of the property is always greater than or equal to 0.

The equivalent C# code is:

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

This code results in a vertical single column list, that has a spacing of 20 around each item:

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

When a CollectionView sets its ItemsLayout property to a GridItemsLayout object, the GridItemsLayout.VerticalItemSpacing and GridItemsLayout.HorizontalItemSpacing properties can be set to double values that represent the empty space vertically and horizontally around each item:

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

Note

The GridItemsLayout.VerticalItemSpacing and GridItemsLayout.HorizontalItemSpacing properties have validation callbacks set, which ensure that the values of the properties are always greater than or equal to 0.

The equivalent C# code is:

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

This code results in a vertical two-column grid, that has a vertical spacing of 20 around each item, and a horizontal spacing of 30 around each item:

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

Item sizing

By default, each item in a CollectionView is individually measured and sized, provided that the UI elements in the DataTemplate don't specify fixed sizes. This behavior, which can be changed, is specified by the CollectionView.ItemSizingStrategy property value. This property value can be set to one of the ItemSizingStrategy enumeration members:

  • MeasureAllItems – each item is individually measured. This is the default value.
  • MeasureFirstItem – only the first item is measured, with all subsequent items being given the same size as the first item.

Important

The MeasureFirstItem sizing strategy will result in increased performance when used in situations where the item size is intended to be uniform across all items.

The following code example shows setting the ItemSizingStrategy property:

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

The equivalent C# code is:

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

Dynamic resizing of items

Items in a CollectionView can be dynamically resized at runtime by changing layout related properties of elements within the DataTemplate. For example, the following code example changes the HeightRequest and WidthRequest properties of an Image object:

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

The OnImageTapped event handler is executed in response to an Image object being tapped, and changes the dimensions of the image so that it's more easily viewed:

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

Right-to-left layout

CollectionView can layout its content in a right-to-left flow direction by setting its FlowDirection property to RightToLeft. However, the FlowDirection property should ideally be set on a page or root layout, which causes all the elements within the page, or root layout, to respond to the flow direction:

<?xml version="1.0" encoding="UTF-8"?>
<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>

The default FlowDirection for an element with a parent is MatchParent. Therefore, the CollectionView inherits the FlowDirection property value from the StackLayout, which in turn inherits the FlowDirection property value from the ContentPage. This results in the right-to-left layout shown in the following screenshots:

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

For more information about flow direction, see Right-to-left localization.