Personalizando a aparência da célula ListView

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.

Construído em células

Xamarin.Forms Vem com células integradas que funcionam para muitas aplicações:

  • 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 verdadeiro/falso.
  • 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.

CélulaDeTexto

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

Exemplo de TextCell padrão

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

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

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

Exemplo de TextCell personalizado

CélulaDeImagem

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

A captura de tela a seguir mostra ImageCell 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 que é mostrado na primeira linha, em fonte grande
  • Detail – o texto que é mostrado abaixo da primeira linha, em uma fonte menor
  • TextColor – a cor do texto
  • DetailColor – a cor do texto detalhado
  • ImageSource – a imagem a ser exibida ao lado do texto

A captura de tela a seguir mostra ImageCell itens com propriedades de cor 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, você pode apresentar uma célula com dois rótulos com peso igual. A TextCell seria insuficiente porque tem TextCell um rótulo menor. A maioria das personalizações de células adiciona dados somente leitura adicionais (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élula 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 está aninhada dentro de um , que está dentro de ListView.ItemTemplate.DataTemplate Este é o mesmo processo que usar qualquer célula interna.
  • ViewCell é o tipo da célula personalizada. O filho do DataTemplate elemento deve ser da classe ou derivar dela ViewCell .
  • Dentro do , o layout pode ser gerenciado ViewCellpor qualquer Xamarin.Forms layout. Neste exemplo, o layout é gerenciado por um StackLayout, que permite que a cor de fundo seja personalizada.

Observação

Qualquer propriedade que seja associável pode ser vinculada dentro de StackLayout 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 no código. Primeiro, uma classe personalizada que deriva 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 do ItemTemplate ListView é 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 às instâncias de um tipo de BindableProperty célula personalizado, os controles de interface do 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 BindingContextChanged evento for acionado, em resposta à alteração do valor da BindingContext propriedade. Portanto, quando as BindingContext alterações, os controles da 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 para Xamarin.Forms coleta de lixo, o que, por sua vez, resultará na chamada de OnBindingContextChanged substituição.

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

Observação

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

Em 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 , Age, e Location associáveis na CustomCell instância, às Namepropriedades , Age, e 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 os ListView elementos is recycling 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 são reutilizadas, seus valores de propriedade são alterados quando o contexto de associação é 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 reciclagem de células, consulte Estratégia de cache.