Share via


Um exemplo básico de RecyclerView

Para entender como RecyclerView funciona em um aplicativo típico, este tópico explora um exemplo de código simples que usa RecyclerView para exibir uma grande coleção de fotos:

Duas capturas de tela de um aplicativo RecyclerView que usa CardViews para exibir fotos

O RecyclerViewer usa CardView para implementar cada item de fotografia no RecyclerViewlayout. Devido às vantagens de desempenho do , este aplicativo de RecyclerViewexemplo é capaz de rolar rapidamente através de uma grande coleção de fotos sem problemas e sem atrasos perceptíveis.

Uma fonte de dados de exemplo

Neste aplicativo de exemplo, uma fonte de dados de "álbum de fotos" (representada pela classe) fornece RecyclerView conteúdo de PhotoAlbum item. PhotoAlbum é uma coleção de fotos com legendas; Ao instanciá-lo, você obtém uma coleção pronta de 32 fotos:

PhotoAlbum mPhotoAlbum = new PhotoAlbum ();

Cada ocorrência de foto em PhotoAlbum expõe propriedades que permitem que você leia sua ID PhotoIDde recurso de imagem e sua cadeia de caracteres de legenda, Caption. A coleção de fotos é organizada de forma que cada foto possa ser acessada por um indexador. Por exemplo, as seguintes linhas de código acessam o ID do recurso de imagem e a legenda da décima foto da coleção:

int imageId = mPhotoAlbum[9].ImageId;
string caption = mPhotoAlbum[9].Caption;

PhotoAlbum também fornece um RandomSwap método que você pode chamar para trocar a primeira foto da coleção por uma foto escolhida aleatoriamente em outro lugar da coleção:

mPhotoAlbum.RandomSwap ();

Como os detalhes da implementação do não são relevantes para a compreensão RecyclerViewdo PhotoAlbum , o código-fonte PhotoAlbum não é apresentado aqui.

Layout e inicialização

O arquivo de layout, Main.axml, consiste em um único RecyclerView dentro de um LinearLayout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:scrollbars="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
</LinearLayout>

Observe que você deve usar o nome totalmente qualificado android.support.v7.widget.RecyclerView porque RecyclerView é empacotado em uma biblioteca de suporte. O OnCreate método de inicializa esse layout, instancia o adaptador e prepara a fonte de MainActivity dados subjacente:

public class MainActivity : Activity
{
    RecyclerView mRecyclerView;
    RecyclerView.LayoutManager mLayoutManager;
    PhotoAlbumAdapter mAdapter;
    PhotoAlbum mPhotoAlbum;

    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);

        // Prepare the data source:
        mPhotoAlbum = new PhotoAlbum ();

        // Instantiate the adapter and pass in its data source:
        mAdapter = new PhotoAlbumAdapter (mPhotoAlbum);

        // Set our view from the "main" layout resource:
        SetContentView (Resource.Layout.Main);

        // Get our RecyclerView layout:
        mRecyclerView = FindViewById<RecyclerView> (Resource.Id.recyclerView);

        // Plug the adapter into the RecyclerView:
        mRecyclerView.SetAdapter (mAdapter);

Este código faz o seguinte:

  1. Instancia a PhotoAlbum fonte de dados.

  2. Passa a fonte de dados do álbum de fotos para o construtor do adaptador PhotoAlbumAdapter (que é definido posteriormente neste guia). Observe que é considerada uma prática recomendada passar a fonte de dados como um parâmetro para o construtor do adaptador.

  3. Obtém o RecyclerView do layout.

  4. Conecta o adaptador à RecyclerView instância chamando o RecyclerViewSetAdapter método conforme mostrado acima.

Gerenciador de Layout

Cada item no é composto por um CardView que contém uma imagem de foto e legenda RecyclerView de foto (os detalhes são abordados na seção View Holder abaixo). O predefinido LinearLayoutManager é usado para dispor cada CardView um em uma disposição de rolagem vertical:

mLayoutManager = new LinearLayoutManager (this);
mRecyclerView.SetLayoutManager (mLayoutManager);

Esse código reside no método da OnCreate atividade principal. O construtor para o gerenciador de layout requer um contexto, então o MainActivity é passado usando this como visto acima.

Em vez de usar o predefinido LinearLayoutManager, você pode conectar um gerenciador de layout personalizado que exibe dois CardView itens lado a lado, implementando um efeito de animação de virada de página para percorrer a coleção de fotos. Mais adiante neste guia, você verá um exemplo de como modificar o layout trocando em um gerenciador de layout diferente.

Suporte de vista

A classe de suporte de exibição é chamada PhotoViewHolderde . Cada PhotoViewHolder instância contém referências ao ImageView e TextView de um item de linha associado, que é disposto em um CardView diagrama aqui:

Diagrama de CardView contendo um ImageView e TextView

PhotoViewHolder deriva de RecyclerView.ViewHolder e contém propriedades para armazenar referências ao ImageView e TextView mostrado no layout acima. PhotoViewHolder consiste em duas propriedades e um construtor:

public class PhotoViewHolder : RecyclerView.ViewHolder
{
    public ImageView Image { get; private set; }
    public TextView Caption { get; private set; }

    public PhotoViewHolder (View itemView) : base (itemView)
    {
        // Locate and cache view references:
        Image = itemView.FindViewById<ImageView> (Resource.Id.imageView);
        Caption = itemView.FindViewById<TextView> (Resource.Id.textView);
    }
}

Neste exemplo de código, o PhotoViewHolder construtor é passada uma referência para o modo de exibição de item pai (o CardView) que PhotoViewHolder quebra. Observe que você sempre encaminha o modo de exibição de item pai para o construtor base. O PhotoViewHolder construtor chama FindViewById o modo de exibição de item pai para localizar cada uma de suas referências ImageView de exibição filho e TextView, armazenando os resultados nas Image propriedades e Caption , respectivamente. Mais tarde, o adaptador recupera referências de exibição dessas propriedades quando atualiza as exibições filho desse CardViewcom novos dados.

Para obter mais informações sobre RecyclerView.ViewHoldero , consulte a referência de classe RecyclerView.ViewHolder.

Adaptador

O adaptador carrega cada RecyclerView linha com dados para uma fotografia específica. Para uma determinada fotografia na posição da linha P, por exemplo, o adaptador localiza os dados associados na posição P dentro da fonte de dados e copia esses dados para o item de linha na posição P na RecyclerView coleção. O adaptador usa o suporte de exibição para pesquisar as referências para o ImageView e TextView nessa posição, para que ele não precise chamar FindViewById repetidamente para esses modos de exibição enquanto o usuário rola pela coleção de fotografias e reutiliza modos de exibição.

Em RecyclerViewer, uma classe de adaptador é derivada de RecyclerView.Adapter para criar PhotoAlbumAdapter:

public class PhotoAlbumAdapter : RecyclerView.Adapter
{
    public PhotoAlbum mPhotoAlbum;

    public PhotoAlbumAdapter (PhotoAlbum photoAlbum)
    {
        mPhotoAlbum = photoAlbum;
    }
    ...
}

O mPhotoAlbum membro contém a fonte de dados (o álbum de fotos) que é passada para o construtor, o construtor copia o álbum de fotos para essa variável de membro. Os seguintes métodos necessários RecyclerView.Adapter são implementados:

  • OnCreateViewHolder – Instancia o arquivo de layout do item e o suporte da exibição.

  • OnBindViewHolder – Carrega os dados na posição especificada nas visualizações cujas referências são armazenadas no titular da visualização dada.

  • ItemCount – Retorna o número de itens na fonte de dados.

O gerenciador de layout chama esses métodos enquanto está posicionando itens dentro do RecyclerView. A implementação desses métodos é examinada nas seções a seguir.

OnCreateViewHolder

O gerenciador de layout chama OnCreateViewHolder quando precisa RecyclerView de um novo suporte de exibição para representar um item. OnCreateViewHolder infla o modo de exibição de item do arquivo de layout do modo de exibição e encapsula o modo de exibição em uma nova PhotoViewHolder instância. O PhotoViewHolder construtor localiza e armazena referências a modos de exibição filho no layout, conforme descrito anteriormente em View Holder.

Cada item de linha é representado por um CardView que contém um ImageView (para a foto) e um TextView (para a legenda). Esse layout reside no arquivo PhotoCardView.axml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:card_view="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        card_view:cardElevation="4dp"
        card_view:cardUseCompatPadding="true"
        card_view:cardCornerRadius="5dp">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:padding="8dp">
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/imageView"
                android:scaleType="centerCrop" />
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:textColor="#333333"
                android:text="Caption"
                android:id="@+id/textView"
                android:layout_gravity="center_horizontal"
                android:layout_marginLeft="4dp" />
        </LinearLayout>
    </android.support.v7.widget.CardView>
</FrameLayout>

Esse layout representa um único item de linha no RecyclerView. O OnBindViewHolder método (descrito abaixo) copia os dados da fonte de dados para o ImageView e TextView deste layout. OnCreateViewHolder infla esse layout para um determinado local de foto no RecyclerView e instancia uma nova PhotoViewHolder instância (que localiza e armazena em cache referências às ImageView exibições e TextView filho no layout associado CardView ):

public override RecyclerView.ViewHolder
    OnCreateViewHolder (ViewGroup parent, int viewType)
{
    // Inflate the CardView for the photo:
    View itemView = LayoutInflater.From (parent.Context).
                Inflate (Resource.Layout.PhotoCardView, parent, false);

    // Create a ViewHolder to hold view references inside the CardView:
    PhotoViewHolder vh = new PhotoViewHolder (itemView);
    return vh;
}

A instância de titular de exibição resultante, vh, é retornada ao chamador (o gerenciador de layout).

OnBindViewHolder

Quando o gerenciador de layout está pronto para exibir uma exibição específica na RecyclerViewárea de tela visível do , ele chama o método do OnBindViewHolder adaptador para preencher o item na posição de linha especificada com o conteúdo da fonte de dados. OnBindViewHolder Obtém as informações da foto para a posição da linha especificada (o recurso de imagem da foto e a cadeia de caracteres para a legenda da foto) e copia esses dados para as exibições associadas. As visualizações são localizadas por meio de referências armazenadas no objeto de suporte de exibição (que é passado através do holder parâmetro):

public override void
    OnBindViewHolder (RecyclerView.ViewHolder holder, int position)
{
    PhotoViewHolder vh = holder as PhotoViewHolder;

    // Load the photo image resource from the photo album:
    vh.Image.SetImageResource (mPhotoAlbum[position].PhotoID);

    // Load the photo caption from the photo album:
    vh.Caption.Text = mPhotoAlbum[position].Caption;
}

O objeto de suporte de exibição passado deve primeiro ser convertido no tipo de suporte de exibição derivado (neste caso, PhotoViewHolder) antes de ser usado. O adaptador carrega o recurso de imagem no modo de exibição referenciado pela propriedade do titular do modo de Image exibição e copia o texto da legenda para o modo de exibição referenciado pela propriedade do titular do modo de Caption exibição. Isso vincula a exibição associada a seus dados.

Observe que OnBindViewHolder é o código que lida diretamente com a estrutura dos dados. Nesse caso, OnBindViewHolder entende como mapear a posição do RecyclerView item para seu item de dados associado na fonte de dados. O mapeamento é simples neste caso porque a posição pode ser usada como um índice de matriz no álbum de fotos; no entanto, fontes de dados mais complexas podem exigir código extra para estabelecer esse mapeamento.

ItemCount

O ItemCount método retorna o número de itens na coleta de dados. No aplicativo visualizador de fotos de exemplo, a contagem de itens é o número de fotos no álbum de fotos:

public override int ItemCount
{
    get { return mPhotoAlbum.NumPhotos; }
}

Para obter mais informações sobre RecyclerView.Adaptero , consulte a referência de classe RecyclerView.Adapter.

Juntando as peças

A implementação resultante RecyclerView para o aplicativo de foto de exemplo consiste em código que cria a fonte de dados, o gerenciador de MainActivity layout e o adaptador. MainActivity Cria a mRecyclerView instância, instancia a fonte de dados e o adaptador e conecta o Gerenciador de layout e o adaptador:

public class MainActivity : Activity
{
    RecyclerView mRecyclerView;
    RecyclerView.LayoutManager mLayoutManager;
    PhotoAlbumAdapter mAdapter;
    PhotoAlbum mPhotoAlbum;

    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);
        mPhotoAlbum = new PhotoAlbum();
        SetContentView (Resource.Layout.Main);
        mRecyclerView = FindViewById<RecyclerView> (Resource.Id.recyclerView);

        // Plug in the linear layout manager:
        mLayoutManager = new LinearLayoutManager (this);
        mRecyclerView.SetLayoutManager (mLayoutManager);

        // Plug in my adapter:
        mAdapter = new PhotoAlbumAdapter (mPhotoAlbum);
        mRecyclerView.SetAdapter (mAdapter);
    }
}

PhotoViewHolder localiza e armazena em cache as referências de exibição:

public class PhotoViewHolder : RecyclerView.ViewHolder
{
    public ImageView Image { get; private set; }
    public TextView Caption { get; private set; }

    public PhotoViewHolder (View itemView) : base (itemView)
    {
        // Locate and cache view references:
        Image = itemView.FindViewById<ImageView> (Resource.Id.imageView);
        Caption = itemView.FindViewById<TextView> (Resource.Id.textView);
    }
}

PhotoAlbumAdapter implementa as três substituições de método necessárias:

public class PhotoAlbumAdapter : RecyclerView.Adapter
{
    public PhotoAlbum mPhotoAlbum;
    public PhotoAlbumAdapter (PhotoAlbum photoAlbum)
    {
        mPhotoAlbum = photoAlbum;
    }

    public override RecyclerView.ViewHolder
        OnCreateViewHolder (ViewGroup parent, int viewType)
    {
        View itemView = LayoutInflater.From (parent.Context).
                    Inflate (Resource.Layout.PhotoCardView, parent, false);
        PhotoViewHolder vh = new PhotoViewHolder (itemView);
        return vh;
    }

    public override void
        OnBindViewHolder (RecyclerView.ViewHolder holder, int position)
    {
        PhotoViewHolder vh = holder as PhotoViewHolder;
        vh.Image.SetImageResource (mPhotoAlbum[position].PhotoID);
        vh.Caption.Text = mPhotoAlbum[position].Caption;
    }

    public override int ItemCount
    {
        get { return mPhotoAlbum.NumPhotos; }
    }
}

Quando esse código é compilado e executado, ele cria o aplicativo básico de visualização de fotos, conforme mostrado nas seguintes capturas de tela:

Duas capturas de tela do aplicativo de visualização de fotos com cartões de fotos de rolagem vertical

Se as sombras não estiverem sendo desenhadas (como visto na captura de tela acima), edite Propriedades/AndroidManifest.xml e adicione a seguinte configuração de atributo ao <application> elemento:

android:hardwareAccelerated="true"

Este aplicativo básico só suporta a navegação do álbum de fotos. Ele não responde a eventos de toque de item, nem manipula alterações nos dados subjacentes. Essa funcionalidade é adicionada em Estendendo o exemplo RecyclerView.

Alterando o LayoutManager

Devido à flexibilidade do , é fácil modificar o aplicativo para usar um gerenciador de RecyclerViewlayout diferente. No exemplo a seguir, ele é modificado para exibir o álbum de fotos com um layout de grade que rola horizontalmente em vez de com um layout linear vertical. Para fazer isso, a instanciação do gerenciador de layout é modificada para usar o GridLayoutManager seguinte:

mLayoutManager = new GridLayoutManager(this, 2, GridLayoutManager.Horizontal, false);

Essa alteração de código substitui a vertical LinearLayoutManager por uma GridLayoutManager que apresenta uma grade composta por duas linhas que rolam na direção horizontal. Ao compilar e executar o aplicativo novamente, você verá que as fotografias são exibidas em uma grade e que a rolagem é horizontal em vez de vertical:

Captura de tela de exemplo do aplicativo com fotos de rolagem horizontal em uma grade

Ao alterar apenas uma linha de código, é possível modificar o aplicativo de visualização de fotos para usar um layout diferente com comportamento diferente. Observe que nem o código do adaptador nem o XML do layout tiveram que ser modificados para alterar o estilo do layout.

No próximo tópico, Estendendo o exemplo RecyclerView, esse aplicativo de exemplo básico é estendido para manipular eventos de clique em item e atualizar RecyclerView quando a fonte de dados subjacente é alterada.