Especificar o layout CollectionView
A interface do usuário do aplicativo .NET multiplataforma (.NET MAUI) CollectionView define as seguintes propriedades que controlam o layout:
ItemsLayout
, do tipoIItemsLayout
, especifica o layout a ser usado.ItemSizingStrategy
, do tipoItemSizingStrategy
, especifica a estratégia de medida de item a ser usada.
Essas propriedades são apoiadas por objetos BindableProperty, o que significa que as propriedades podem ser alvos de vinculações de dados.
Por padrão, um CollectionView exibirá seus itens em uma lista vertical. No entanto, qualquer um dos seguintes layouts pode ser usado:
- Lista vertical – uma lista de colunas únicas que cresce verticalmente à medida que novos itens são adicionados.
- Lista horizontal – uma única lista de linhas que cresce horizontalmente à medida que novos itens são adicionados.
- Grade vertical – uma grade de várias colunas que cresce verticalmente à medida que novos itens são adicionados.
- Grade horizontal – uma grade de várias linhas que cresce horizontalmente à medida que novos itens são adicionados.
Esses layouts podem ser especificados definindo a propriedade ItemsLayout
como class que deriva da classe ItemsLayout
. Essa classe define as seguintes propriedades:
Orientation
, do tipoItemsLayoutOrientation
, especifica a direção na qual o CollectionView se expande à medida que os itens são adicionados.SnapPointsAlignment
, do tipoSnapPointsAlignment
, especifica como os pontos de snap são alinhados com os itens.SnapPointsType
, do tipoSnapPointsType
, especifica o comportamento dos pontos de snap durante a rolagem.
Essas propriedades são apoiadas por objetos BindableProperty, o que significa que as propriedades podem ser alvos de vinculações de dados. Para obter mais informações sobre pontos de ajuste, consulte Pontos de ajuste em Controlar a rolagem em um CollectionView.
A enumeração ItemsLayoutOrientation
define os seguintes membros:
Vertical
indica que o CollectionView se expandirá verticalmente à medida que os itens forem adicionados.Horizontal
indica que o CollectionView se expandirá horizontalmente à medida que os itens forem adicionados.
A classe LinearItemsLayout
herda da classe ItemsLayout
e define uma propriedade ItemSpacing
, do tipo double
, que representa o espaço vazio ao redor de cada item. O valor padrão dessa propriedade é 0 e seu valor deve ser sempre maior ou igual a 0. A classe LinearItemsLayout
também define Vertical
estáticos e membros Horizontal
. Esses membros podem ser usados para criar listas verticais ou horizontais, respectivamente. Como alternativa, um objeto LinearItemsLayout
pode ser criado, especificando um membro de enumeração ItemsLayoutOrientation
como um argumento.
A classe GridItemsLayout
herda da classe ItemsLayout
e define as seguintes propriedades:
VerticalItemSpacing
, do tipodouble
, que representa o espaço vazio vertical ao redor de cada item. O valor padrão dessa propriedade é 0 e seu valor deve ser sempre maior ou igual a 0.HorizontalItemSpacing
, do tipodouble
, que representa o espaço vazio horizontal ao redor de cada item. O valor padrão dessa propriedade é 0 e seu valor deve ser sempre maior ou igual a 0.Span
, do tipoint
, que representa o número de colunas ou linhas a serem exibidas na grade. O valor padrão dessa propriedade é 1 e seu valor deve ser sempre maior ou igual a 1.
Essas propriedades são apoiadas por objetos BindableProperty, o que significa que as propriedades podem ser alvos de vinculações de dados.
Observação
CollectionView usa os mecanismos de layout nativos para executar o layout.
Lista vertical
Por padrão, CollectionView exibirá seus itens em um layout de lista vertical. Portanto, não é necessário definir a propriedade ItemsLayout
para usar esse 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>
No entanto, para fins de integridade, em XAML, um CollectionView pode ser definido para exibir seus itens em uma lista vertical, definindo sua propriedade ItemsLayout
como VerticalList
:
<CollectionView ItemsSource="{Binding Monkeys}"
ItemsLayout="VerticalList">
...
</CollectionView>
Como alternativa, isso também pode ser feito definindo a propriedade ItemsLayout
como um objeto LinearItemsLayout
, especificando o membro de enumeração Vertical
ItemsLayoutOrientation
como o valor da propriedade Orientation
:
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Vertical" />
</CollectionView.ItemsLayout>
...
</CollectionView>
Este é o código C# equivalente:
CollectionView collectionView = new CollectionView
{
...
ItemsLayout = LinearItemsLayout.Vertical
};
Isso resulta em uma lista de colunas únicas, que cresce verticalmente à medida que novos itens são adicionados:
Dica
Colocar um CollectionView dentro de um VerticalStackLayout pode interromper a rolagem do CollectionView e limitar o número de itens exibidos. Nessa situação, substitua o VerticalStackLayout por um Grid.
Lista horizontal
Em XAML, um CollectionView pode exibir seus itens em uma lista horizontal definindo sua propriedade ItemsLayout
como 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>
Como alternativa, esse layout também pode ser feito definindo a propriedade ItemsLayout
como um objeto LinearItemsLayout
, especificando o membro de enumeração Horizontal
ItemsLayoutOrientation
como o valor da propriedade Orientation
:
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal" />
</CollectionView.ItemsLayout>
...
</CollectionView>
Este é o código C# equivalente:
CollectionView collectionView = new CollectionView
{
...
ItemsLayout = LinearItemsLayout.Horizontal
};
Isso resulta em uma única lista de linhas, que cresce horizontalmente à medida que novos itens são adicionados:
Grade vertical
Em XAML, um CollectionView pode exibir seus itens em uma grade vertical definindo sua propriedade ItemsLayout
como VerticalGrid
:
<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>
Como alternativa, esse layout também pode ser feito definindo a propriedade ItemsLayout
como um objeto GridItemsLayout
cuja propriedade Orientation
está definida como Vertical
:
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical"
Span="2" />
</CollectionView.ItemsLayout>
...
</CollectionView>
Este é o código C# equivalente:
CollectionView collectionView = new CollectionView
{
...
ItemsLayout = new GridItemsLayout(2, ItemsLayoutOrientation.Vertical)
};
Por padrão, um GridItemsLayout
vertical exibirá itens em uma única coluna. No entanto, este exemplo define a propriedade GridItemsLayout.Span
como 2. Isso resulta em uma grade de duas colunas, que cresce verticalmente à medida que novos itens são adicionados:
Grade horizontal
Em XAML, um CollectionView pode exibir seus itens em uma grade horizontal definindo sua propriedade ItemsLayout
como HorizontalGrid
:
<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>
Como alternativa, esse layout também pode ser feito definindo a propriedade ItemsLayout
como um objeto GridItemsLayout
cuja propriedade Orientation
está definida como Horizontal
:
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Horizontal"
Span="4" />
</CollectionView.ItemsLayout>
...
</CollectionView>
Este é o código C# equivalente:
CollectionView collectionView = new CollectionView
{
...
ItemsLayout = new GridItemsLayout(4, ItemsLayoutOrientation.Horizontal)
};
Por padrão, um GridItemsLayout
horizontal exibirá itens em uma única linha. No entanto, este exemplo define a propriedade GridItemsLayout.Span
como 4. Isso resulta em uma grade de quatro linhas, que cresce horizontalmente à medida que novos itens são adicionados:
Cabeçalhos e rodapés
CollectionView pode apresentar um cabeçalho e rodapé que rola com os itens da lista. O cabeçalho e o rodapé podem ser strings, visualizações ou objetos DataTemplate.
CollectionView define as seguintes propriedades para especificar o cabeçalho e o rodapé:
Header
, do tipoobject
, especifica a string, ligação ou visualização que será exibida no início da lista.HeaderTemplate
, do tipo DataTemplate, especifica o DataTemplate a ser usado para formatar oHeader
.Footer
, do tipoobject
, especifica a string, ligação ou visualização que será exibida no final da lista.FooterTemplate
, do tipo DataTemplate, especifica o DataTemplate a ser usado para formatar oFooter
.
Essas propriedades são apoiadas por objetos BindableProperty, o que significa que as propriedades podem ser alvos de vinculações de dados.
Quando um cabeçalho é adicionado a um layout que cresce horizontalmente, da esquerda para a direita, o cabeçalho é exibido à esquerda da lista. Da mesma forma, quando um rodapé é adicionado a um layout que cresce horizontalmente, da esquerda para a direita, o rodapé é exibido à direita da lista.
Exibir strings no cabeçalho e no rodapé
As propriedades Header
e Footer
podem ser definidas como valores string
, conforme mostrado no exemplo a seguir:
<CollectionView ItemsSource="{Binding Monkeys}"
Header="Monkeys"
Footer="2019">
...
</CollectionView>
Este é o código C# equivalente:
CollectionView collectionView = new CollectionView
{
Header = "Monkeys",
Footer = "2019"
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
Esse código resulta nas seguintes capturas de tela, com o cabeçalho mostrado na captura de tela do iOS e o rodapé mostrado na captura de tela do Android:
Exibir exibições no cabeçalho e no rodapé
As propriedades Header
e Footer
podem ser definidas para uma visualização. Pode ser uma exibição única ou uma exibição que contém várias exibições filho. O exemplo a seguir mostra as propriedades Header
e Footer
cada uma definida para um objeto StackLayout que contém um objeto Label:
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.Header>
<StackLayout BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Text="Monkeys"
FontSize="12"
FontAttributes="Bold" />
</StackLayout>
</CollectionView.Header>
<CollectionView.Footer>
<StackLayout BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Text="Friends of Xamarin Monkey"
FontSize="12"
FontAttributes="Bold" />
</StackLayout>
</CollectionView.Footer>
...
</CollectionView>
Este é o código C# equivalente:
StackLayout headerStackLayout = new StackLayout();
header.StackLayout.Add(new Label { Text = "Monkeys", ... } );
StackLayout footerStackLayout = new StackLayout();
footerStackLayout.Add(new Label { Text = "Friends of Xamarin Monkey", ... } );
CollectionView collectionView = new CollectionView
{
Header = headerStackLayout,
Footer = footerStackLayout
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
Esse código resulta nas seguintes capturas de tela, com o cabeçalho mostrado na captura de tela do iOS e o rodapé mostrado na captura de tela do Android:
Exibir um modelo de cabeçalho e rodapé
As propriedades HeaderTemplate
e FooterTemplate
podem ser definidas como objetos DataTemplate usados para formatar o cabeçalho e o rodapé. Nesse cenário, as propriedades Header
e Footer
devem ser associadas à fonte atual para que os modelos sejam aplicados, conforme mostrado no exemplo a seguir:
<CollectionView ItemsSource="{Binding Monkeys}"
Header="{Binding .}"
Footer="{Binding .}">
<CollectionView.HeaderTemplate>
<DataTemplate>
<StackLayout BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Text="Monkeys"
FontSize="12"
FontAttributes="Bold" />
</StackLayout>
</DataTemplate>
</CollectionView.HeaderTemplate>
<CollectionView.FooterTemplate>
<DataTemplate>
<StackLayout BackgroundColor="LightGray">
<Label Margin="10,0,0,0"
Text="Friends of Xamarin Monkey"
FontSize="12"
FontAttributes="Bold" />
</StackLayout>
</DataTemplate>
</CollectionView.FooterTemplate>
...
</CollectionView>
Este é o código C# equivalente:
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");
Esse código resulta nas seguintes capturas de tela, com o cabeçalho mostrado na captura de tela do iOS e o rodapé mostrado na captura de tela do Android:
Espaçamento entre itens
Por padrão, não há espaço entre cada item em um CollectionView. Esse comportamento pode ser alterado definindo propriedades no layout de itens usado pelo CollectionView.
Quando um CollectionView define sua propriedade ItemsLayout
como um objeto LinearItemsLayout
, a propriedade LinearItemsLayout.ItemSpacing
pode ser definida como um valor double
que representa o espaço entre os itens:
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Vertical"
ItemSpacing="20" />
</CollectionView.ItemsLayout>
...
</CollectionView>
Observação
A propriedade LinearItemsLayout.ItemSpacing
tem um conjunto de retorno de chamada de validação, o que garante que o valor da propriedade seja sempre maior ou igual a 0.
Este é o código C# equivalente:
CollectionView collectionView = new CollectionView
{
...
ItemsLayout = new LinearItemsLayout(ItemsLayoutOrientation.Vertical)
{
ItemSpacing = 20
}
};
Esse código resulta em uma lista vertical de coluna única que tem um espaçamento de 20 entre os itens:
Quando um CollectionView define sua propriedade ItemsLayout
para um objeto GridItemsLayout
, as propriedades GridItemsLayout.VerticalItemSpacing
e GridItemsLayout.HorizontalItemSpacing
podem ser definidas para double
valores que representam o espaço vazio vertical e horizontalmente entre os itens:
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical"
Span="2"
VerticalItemSpacing="20"
HorizontalItemSpacing="30" />
</CollectionView.ItemsLayout>
...
</CollectionView>
Observação
As propriedades GridItemsLayout.VerticalItemSpacing
e GridItemsLayout.HorizontalItemSpacing
têm retornos de chamada de validação definidos, o que garante que os valores das propriedades sejam sempre maiores ou iguais a 0.
Este é o código C# equivalente:
CollectionView collectionView = new CollectionView
{
...
ItemsLayout = new GridItemsLayout(2, ItemsLayoutOrientation.Vertical)
{
VerticalItemSpacing = 20,
HorizontalItemSpacing = 30
}
};
Esse código resulta em uma grade vertical de duas colunas que tem um espaçamento vertical de 20 entre os itens e um espaçamento horizontal de 30 entre os itens:
Dimensionamento do item
Por padrão, cada item em um CollectionView é medido e dimensionado individualmente, desde que os elementos da interface do usuário no DataTemplate não especifiquem tamanhos fixos. Esse comportamento, que pode ser alterado, é especificado pelo valor da propriedade CollectionView.ItemSizingStrategy
. Esse valor de propriedade pode ser definido como um dos ItemSizingStrategy
membros da enumeração:
MeasureAllItems
– cada item é medido individualmente. Este é o valor padrão.MeasureFirstItem
– apenas o primeiro item é medido, com todos os itens subsequentes recebendo o mesmo tamanho do primeiro item.
Importante
A estratégia de dimensionamento MeasureFirstItem
resultará em maior desempenho quando usada em situações em que o tamanho do item deve ser uniforme em todos os itens.
O exemplo de código a seguir mostra a configuração da propriedade ItemSizingStrategy
:
<CollectionView ...
ItemSizingStrategy="MeasureFirstItem">
...
</CollectionView>
Este é o código C# equivalente:
CollectionView collectionView = new CollectionView
{
...
ItemSizingStrategy = ItemSizingStrategy.MeasureFirstItem
};
Redimensionamento dinâmico de itens
Os itens em um CollectionView podem ser redimensionados dinamicamente no tempo de execução, alterando as propriedades relacionadas ao layout dos elementos dentro do DataTemplate. Por exemplo, o exemplo de código a seguir altera as propriedades HeightRequest e WidthRequest de um objeto Image:
void OnImageTapped(object sender, EventArgs e)
{
Image image = sender as Image;
image.HeightRequest = image.WidthRequest = image.HeightRequest.Equals(60) ? 100 : 60;
}
O manipulador de eventos OnImageTapped
é executado em resposta a um objeto Image que está sendo tocado e altera as dimensões da imagem para que ela seja mais facilmente visualizada:
Layout da direita para a esquerda
CollectionView pode fazer o layout de seu conteúdo em uma direção de fluxo da direita para a esquerda, definindo sua propriedade FlowDirection
como RightToLeft
. Entretanto, o ideal é que a propriedade FlowDirection
seja definida em uma página ou layout raiz, o que faz com que todos os elementos da página ou layout raiz respondam à direção do fluxo:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CollectionViewDemos.Views.VerticalListFlowDirectionPage"
Title="Vertical list (RTL FlowDirection)"
FlowDirection="RightToLeft">
<Grid Margin="20">
<CollectionView ItemsSource="{Binding Monkeys}">
...
</CollectionView>
</Grid>
</ContentPage>
O padrão FlowDirection
para um elemento com um pai é MatchParent
. Portanto, o CollectionView herda o valor da propriedade FlowDirection
do Grid, que, por sua vez, herda o valor da propriedade FlowDirection
do ContentPage. Isso resulta no layout da direita para a esquerda mostrado na captura de tela a seguir:
Para obter mais informações sobre a direção do fluxo, consulte Localização da direita para a esquerda.