Personalizando a aparência da célula ListView

Baixar exemplo Baixar o exemplo

A Xamarin.FormsListView classe é usada para apresentar listas roláveis, que podem ser personalizadas por meio do uso de ViewCell elementos. Um ViewCell elemento pode exibir texto e imagens, indicar um estado verdadeiro/falso e receber entrada do usuário.

Células internas

Xamarin.Forms vem com células internas que funcionam para muitos aplicativos:

  • TextCell os controles são usados para exibir texto com uma segunda linha opcional para texto detalhado.
  • ImageCell os controles são semelhantes a TextCells, mas incluem uma imagem à esquerda do texto.
  • SwitchCell os controles são usados para apresentar e capturar estados ativados/desativados ou verdadeiros/falsos.
  • EntryCell os controles são usados para apresentar dados de texto que o usuário pode editar.

Os SwitchCell controles e EntryCell são mais comumente usados no contexto de um TableView.

TextCell

TextCell é uma célula para exibir texto, opcionalmente com uma segunda linha como texto detalhado. A captura de tela a seguir mostra TextCell os itens no iOS e no Android:

Exemplo de TextCell padrão

TextCells são renderizados como controles nativos em runtime, portanto, o desempenho é muito bom em comparação com um personalizado ViewCell. TextCells são personalizáveis, permitindo que você defina as seguintes propriedades:

  • Text – o texto mostrado na primeira linha, em fonte grande.
  • Detail – o texto mostrado abaixo da primeira linha, em uma fonte menor.
  • TextColor – a cor do texto.
  • DetailColor – a cor do texto de detalhes

A captura de tela a seguir mostra TextCell itens com propriedades de cores personalizadas:

Exemplo de TextCell personalizado

ImageCell

ImageCell, como TextCell, pode ser usado para exibir texto e texto de detalhes secundários e oferece um ótimo desempenho usando os controles nativos de cada plataforma. ImageCell difere de TextCell em que exibe uma imagem à esquerda do texto.

A captura de tela a seguir mostra ImageCell os itens no iOS e no Android:

ImageCell é útil quando você precisa exibir uma lista de dados com um aspecto visual, como uma lista de contatos ou filmes. ImageCells são personalizáveis, permitindo que você defina:

  • Text – o texto mostrado na primeira linha, em fonte grande
  • Detail – o texto mostrado abaixo da primeira linha, em uma fonte menor
  • TextColor – a cor do texto
  • DetailColor – a cor do texto de detalhes
  • ImageSource – a imagem a ser exibida ao lado do texto

A captura de tela a seguir mostra ImageCell itens com propriedades de cores personalizadas:

Células personalizadas

As células personalizadas permitem que você crie layouts de célula que não são compatíveis com as células internas. Por exemplo, talvez você queira apresentar uma célula com dois rótulos com peso igual. Um TextCell seria insuficiente porque o TextCell tem um rótulo menor. A maioria das personalizações de células adicionais adicionais somente leitura (como rótulos adicionais, imagens ou outras informações de exibição).

Todas as células personalizadas devem derivar de ViewCell, a mesma classe base que todos os tipos de células internos usam.

Xamarin.Forms oferece um comportamento de cache no controle que pode melhorar o ListView desempenho de rolagem para alguns tipos de células personalizadas.

A captura de tela a seguir mostra um exemplo de uma célula personalizada:

XAML

A célula personalizada mostrada na captura de tela anterior pode ser criada com o seguinte XAML:

<?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="demoListView.ImageCellPage">
    <ContentPage.Content>
        <ListView  x:Name="listView">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout BackgroundColor="#eee"
                        Orientation="Vertical">
                            <StackLayout Orientation="Horizontal">
                                <Image Source="{Binding image}" />
                                <Label Text="{Binding title}"
                                TextColor="#f35e20" />
                                <Label Text="{Binding subtitle}"
                                HorizontalOptions="EndAndExpand"
                                TextColor="#503026" />
                            </StackLayout>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </ContentPage.Content>
</ContentPage>

O XAML funciona da seguinte maneira:

  • A célula personalizada é aninhada dentro de um DataTemplate, que está dentro ListView.ItemTemplatede . Esse é o mesmo processo que usar qualquer célula interna.
  • ViewCell é o tipo da célula personalizada. O filho do DataTemplate elemento deve ser de ou derivar da ViewCell classe .
  • Dentro do , o ViewCelllayout pode ser gerenciado por qualquer Xamarin.Forms layout. Neste exemplo, o layout é gerenciado por um StackLayout, que permite que a cor da tela de fundo seja personalizada.

Observação

Qualquer propriedade que StackLayout seja associável pode ser associada dentro de uma célula personalizada. No entanto, essa funcionalidade não é mostrada no exemplo XAML.

Código

Uma célula personalizada também pode ser criada em código. Primeiro, uma classe personalizada derivada de ViewCell deve ser criada:

public class CustomCell : ViewCell
    {
        public CustomCell()
        {
            //instantiate each of our views
            var image = new Image ();
            StackLayout cellWrapper = new StackLayout ();
            StackLayout horizontalLayout = new StackLayout ();
            Label left = new Label ();
            Label right = new Label ();

            //set bindings
            left.SetBinding (Label.TextProperty, "title");
            right.SetBinding (Label.TextProperty, "subtitle");
            image.SetBinding (Image.SourceProperty, "image");

            //Set properties for desired design
            cellWrapper.BackgroundColor = Color.FromHex ("#eee");
            horizontalLayout.Orientation = StackOrientation.Horizontal;
            right.HorizontalOptions = LayoutOptions.EndAndExpand;
            left.TextColor = Color.FromHex ("#f35e20");
            right.TextColor = Color.FromHex ("503026");

            //add views to the view hierarchy
            horizontalLayout.Children.Add (image);
            horizontalLayout.Children.Add (left);
            horizontalLayout.Children.Add (right);
            cellWrapper.Children.Add (horizontalLayout);
            View = cellWrapper;
        }
    }

No construtor de página, a propriedade ListView ItemTemplate é definida como um DataTemplate com o CustomCell tipo especificado:

public partial class ImageCellPage : ContentPage
    {
        public ImageCellPage ()
        {
            InitializeComponent ();
            listView.ItemTemplate = new DataTemplate (typeof(CustomCell));
        }
    }

Alterações de contexto de associação

Ao associar a instâncias de um tipo de célula personalizado, os controles de interface do BindableProperty usuário que exibem os BindableProperty valores devem usar a OnBindingContextChanged substituição para definir os dados a serem exibidos em cada célula, em vez do construtor de célula, conforme demonstrado no exemplo de código a seguir:

public class CustomCell : ViewCell
{
    Label nameLabel, ageLabel, locationLabel;

    public static readonly BindableProperty NameProperty =
        BindableProperty.Create ("Name", typeof(string), typeof(CustomCell), "Name");
    public static readonly BindableProperty AgeProperty =
        BindableProperty.Create ("Age", typeof(int), typeof(CustomCell), 0);
    public static readonly BindableProperty LocationProperty =
        BindableProperty.Create ("Location", typeof(string), typeof(CustomCell), "Location");

    public string Name
    {
        get { return(string)GetValue (NameProperty); }
        set { SetValue (NameProperty, value); }
    }

    public int Age
    {
        get { return(int)GetValue (AgeProperty); }
        set { SetValue (AgeProperty, value); }
    }

    public string Location
    {
        get { return(string)GetValue (LocationProperty); }
        set { SetValue (LocationProperty, value); }
    }
    ...

    protected override void OnBindingContextChanged ()
    {
        base.OnBindingContextChanged ();

        if (BindingContext != null)
        {
            nameLabel.Text = Name;
            ageLabel.Text = Age.ToString ();
            locationLabel.Text = Location;
        }
    }
}

A OnBindingContextChanged substituição será chamada quando o evento for acionado BindingContextChanged , em resposta ao valor da BindingContext propriedade mudando. Portanto, quando o BindingContext é alterado, os controles de interface do usuário que exibem os BindableProperty valores devem definir seus dados. Observe que o BindingContext deve ser verificado quanto a um null valor, pois isso pode ser definido por Xamarin.Forms para coleta de lixo, o OnBindingContextChanged que, por sua vez, resultará na substituição que está sendo chamada.

Como alternativa, os controles de interface do BindableProperty usuário podem se associar às instâncias para exibir seus valores, o que remove a necessidade de substituir o OnBindingContextChanged método.

Observação

Ao substituir OnBindingContextChanged, verifique se o método da OnBindingContextChanged classe base é chamado para que os delegados registrados recebam o BindingContextChanged evento.

No XAML, a associação do tipo de célula personalizada aos dados pode ser obtida conforme mostrado no exemplo de código a seguir:

<ListView x:Name="listView">
    <ListView.ItemTemplate>
        <DataTemplate>
            <local:CustomCell Name="{Binding Name}" Age="{Binding Age}" Location="{Binding Location}" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Isso associa as Namepropriedades , Agee Location associáveis na CustomCell instância, às Namepropriedades , Agee Location de cada objeto na coleção subjacente.

A associação equivalente em C# é mostrada no seguinte exemplo de código:

var customCell = new DataTemplate (typeof(CustomCell));
customCell.SetBinding (CustomCell.NameProperty, "Name");
customCell.SetBinding (CustomCell.AgeProperty, "Age");
customCell.SetBinding (CustomCell.LocationProperty, "Location");

var listView = new ListView
{
    ItemsSource = people,
    ItemTemplate = customCell
};

No iOS e no Android, se o ListView estiver reciclando elementos e a célula personalizada usar um renderizador personalizado, o renderizador personalizado deverá implementar corretamente a notificação de alteração de propriedade. Quando as células forem reutilizados, seus valores de propriedade serão alterados quando o contexto de associação for atualizado para o de uma célula disponível, com PropertyChanged eventos sendo gerados. Para obter mais informações, consulte Personalizando um ViewCell. Para obter mais informações sobre a reciclagem de células, consulte Estratégia de cache.