Partilhar via


Estendendo o exemplo RecyclerView

O aplicativo básico descrito em A Basic RecyclerView Example na verdade não faz muito – ele simplesmente rola e exibe uma lista fixa de itens de fotografia para facilitar a navegação. Em aplicativos do mundo real, os usuários esperam poder interagir com o aplicativo tocando em itens na tela. Além disso, a fonte de dados subjacente pode ser alterada (ou alterada pelo aplicativo) e o conteúdo da exibição deve permanecer consistente com essas alterações. Nas seções a seguir, você aprenderá a lidar com eventos de clique em itens e atualizar RecyclerView quando a fonte de dados subjacente for alterada.

Manipulando eventos de clique no item

Quando um usuário toca em um item no , um evento de clique no RecyclerViewitem é gerado para notificar o aplicativo sobre qual item foi tocado. Esse evento não é gerado por RecyclerView – em vez disso, o modo de exibição de item (que é encapsulado no suporte de exibição) detecta toques e relata esses toques como eventos de clique.

Para ilustrar como manipular eventos de clique em item, as etapas a seguir explicam como o aplicativo básico de visualização de fotos é modificado para relatar qual fotografia foi tocada pelo usuário. Quando ocorre um evento de clique em item no aplicativo de exemplo, ocorre a seguinte sequência:

  1. A fotografia detecta CardView o evento de clique no item e notifica o adaptador.

  2. O adaptador encaminha o evento (com informações de posição do item) para o manipulador de clique no item da atividade.

  3. O manipulador de clique em item da atividade responde ao evento de clique em item.

Primeiro, um membro do manipulador de eventos chamado ItemClick é adicionado à definição de PhotoAlbumAdapter classe:

public event EventHandler<int> ItemClick;

Em seguida, um método de manipulador de eventos item-click é adicionado ao MainActivity. Esse manipulador exibe brevemente uma notificação do sistema que indica qual item de fotografia foi tocado:

void OnItemClick (object sender, int position)
{
    int photoNum = position + 1;
    Toast.MakeText(this, "This is photo number " + photoNum, ToastLength.Short).Show();
}

Em seguida, uma linha de código é necessária para registrar o OnItemClick manipulador com PhotoAlbumAdapter. Um bom lugar para fazer isso é imediatamente após PhotoAlbumAdapter a criação:

mAdapter = new PhotoAlbumAdapter (mPhotoAlbum);
mAdapter.ItemClick += OnItemClick;

Neste exemplo básico, o registro do manipulador ocorre no método da atividade principal, mas um aplicativo de OnCreate produção pode registrar o manipulador e OnResume cancelá-lo – OnPause consulte Ciclo de vida da atividade para obter mais informações.

PhotoAlbumAdapter agora OnItemClick chamará quando receber um evento de clique no item. A próxima etapa é criar um manipulador no adaptador que gera esse ItemClick evento. O seguinte método, OnClick, é adicionado imediatamente após o método do ItemCount adaptador:

void OnClick (int position)
{
    if (ItemClick != null)
        ItemClick (this, position);
}

Esse OnClick método é o ouvinte do adaptador para eventos de clique em item de exibições de item. Antes que esse ouvinte possa ser registrado com um modo de exibição de item (por meio do suporte de exibição do modo de exibição de item), o PhotoViewHolder construtor deve ser modificado para aceitar esse método como um argumento adicional e registrar OnClick com o evento de exibição Click de item. Aqui está o construtor modificado PhotoViewHolder :

public PhotoViewHolder (View itemView, Action<int> listener)
    : base (itemView)
{
    Image = itemView.FindViewById<ImageView> (Resource.Id.imageView);
    Caption = itemView.FindViewById<TextView> (Resource.Id.textView);

    itemView.Click += (sender, e) => listener (base.LayoutPosition);
}

O itemView parâmetro contém uma referência ao CardView que foi tocado pelo usuário. Observe que a classe base do titular do modo de exibição sabe a posição de layout do item (CardView) que ele representa (por meio da LayoutPosition propriedade), e essa posição é passada para o método do OnClick adaptador quando ocorre um evento de clique no item. O método do OnCreateViewHolder adaptador é modificado para passar o método do OnClick adaptador para o construtor do suporte de exibição:

PhotoViewHolder vh = new PhotoViewHolder (itemView, OnClick);

Agora, quando você cria e executa o aplicativo de visualização de fotos de amostra, tocar em uma foto na tela fará com que uma notificação do sistema apareça informando qual fotografia foi tocada:

Exemplo de notificação do sistema que aparece quando um cartão de foto é tocado

Este exemplo demonstra apenas uma abordagem para implementar manipuladores de eventos com RecyclerViewo . Outra abordagem que pode ser usada aqui é colocar eventos no suporte de exibição e fazer com que o adaptador assine esses eventos. Se o aplicativo de foto de amostra fornecesse um recurso de edição de fotos, eventos separados seriam necessários para o ImageView e dentro de TextView cada CardView: toca no TextView iniciaria uma EditView caixa de diálogo que permite ao usuário editar a legenda e tocaria na ImageView ferramenta iniciaria um retoque de foto que permite ao usuário cortar ou girar a foto. Dependendo das necessidades do seu aplicativo, você deve projetar a melhor abordagem para lidar e responder a eventos de toque.

Para demonstrar como RecyclerView pode ser atualizado quando o conjunto de dados é alterado, o aplicativo de visualização de fotos de exemplo pode ser modificado para escolher aleatoriamente uma foto na fonte de dados e trocá-la pela primeira foto. Primeiro, um botão Escolha aleatória é adicionado ao layout Main.axml do aplicativo de fotos de exemplo:

<?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">
    <Button
        android:id="@+id/randPickButton"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Random Pick" />
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:scrollbars="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
</LinearLayout>

Em seguida, o código é adicionado no final do método da atividade OnCreate principal para localizar o Random Pick botão no layout e anexar um manipulador a ele:

Button randomPickBtn = FindViewById<Button>(Resource.Id.randPickButton);

randomPickBtn.Click += delegate
{
    if (mPhotoAlbum != null)
    {
        // Randomly swap a photo with the first photo:
        int idx = mPhotoAlbum.RandomSwap();
    }
};

Esse manipulador chama o método do álbum de RandomSwap fotos quando o botão Seleção aleatória é tocado. O RandomSwap método troca aleatoriamente uma foto pela primeira foto na fonte de dados e, em seguida, retorna o índice da foto trocada aleatoriamente. Quando você compila e executa o aplicativo de exemplo com esse código, tocar no botão Seleção aleatória não resulta em uma alteração de exibição porque o RecyclerView não está ciente da alteração na fonte de dados.

Para se manter RecyclerView atualizado após as alterações da fonte de dados, o manipulador de clique de Seleção Aleatória deve ser modificado para chamar o método do NotifyItemChanged adaptador para cada item da coleção que foi alterado (nesse caso, dois itens foram alterados: a primeira foto e a foto trocada). Isso faz com RecyclerView que a atualização de sua exibição seja consistente com o novo estado da fonte de dados:

Button randomPickBtn = FindViewById<Button>(Resource.Id.randPickButton);

randomPickBtn.Click += delegate
{
    if (mPhotoAlbum != null)
    {
        int idx = mPhotoAlbum.RandomSwap();

        // First photo has changed:
        mAdapter.NotifyItemChanged(0);

        // Swapped photo has changed:
        mAdapter.NotifyItemChanged(idx);
    }
};

Agora, quando o botão Seleção aleatória é tocado, RecyclerView atualiza a exibição para mostrar que uma foto mais abaixo na coleção foi trocada pela primeira foto da coleção:

Primeira captura de tela antes da troca, segunda captura de tela após a troca

Claro, poderia ter sido chamado em vez de fazer as duas chamadas para NotifyItemChanged, mas isso forçaria RecyclerView a atualizar toda a coleção, NotifyDataSetChanged mesmo que apenas dois itens da coleção tivessem mudado. Chamar NotifyItemChanged é significativamente mais eficiente do que chamar NotifyDataSetChanged.