0

RecyclerView 101: capture cliques curtos e longos

#Kotlin #Android
Francisco Rasia
Francisco Rasia

A RecyclerView é o virtual padrão para exibir listas de dados, menus de botões e outros componentes no Android. Ela permite criar itens com layouts ricos e interativos, com checkboxes, botões, barras de rating, e assim por diante. Mas acessar os itens de uma RecyclerView e interagir com seus componentes internos é um pouco mais complicado do que fazê-lo em uma ListView.

Esse é o primeiro de uma série de artigos em que pretendo explorar várias maneiras de interagir com os itens de uma RecyclerView. Vamos começar pelas interações mais simples: clicar em um item para ver os seus detalhes e fazer um clique longo em um item para removê-lo da lista.


🐱 O Pulo do gato

A grande diferença entre a captura de cliques em itens de uma RecyclerView e em outros componentes do Android é a necessidade de se implementar uma interface para tratar esses comportamentos. A classe que implementar essa interface vai atuar como um Listener ("escutador") de cliques nos componentes internos da RecyclerView.

Existem várias maneiras de se implementar essa solução. Eis um roteiro possível:

1. Criar uma interface ItemClickListener

Por exemplo, para criar uma interface que trate cliques longos e curtos, declaramos dois métodos diferentes:

 interface ClickItemTarefaListener {
   fun onItemClickListener(tarefa: Tarefa)
   fun onItemLongClickListener(tarefa: Tarefa)
 }


Como se trata de uma interface, esses métodos não têm corpo, e deverão ser sobrescritos na classe que "assinar o contrato" com a interface, ou seja, a que vier a implementá-la.


2.Modificar o construtor do Adapter e do ViewHolder para que recebam essa interface como parâmetro

O Adapter vai passar a receber a interface como parâmetro via construtor; esse listener pode estão ser repassado como parâmetro durante a criação do ViewHolder:

//o construtor do adapter precisa receber um listener
class TarefaAdapter(val listener: ClickItemTarefaListener) :
  RecyclerView.Adapter<TarefaAdapter.TarefaAdapterViewHolder>() {
​
 //...
​
  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TarefaAdapterViewHolder {
    binding = TarefaItemBinding.inflate(
      LayoutInflater.from(parent.context),
      parent, false
   )
  //construindo um ViewHolder com o listener
    return TarefaAdapterViewHolder(binding, listener = listener, lista=lista)
 }

3. Vincular os ViewHolders aos comportamentos do Listener

Pode ser feito, por exemplo, ao se instanciar os ViewHolders por meio do bloco init { } (nesse caso, passando a view inteira como objeto do OnClickListener):

init {
 //para o clique curto
  binding.root.setOnClickListener {
    //chame o método da interface...
    listener.onItemClickListener(lista[adapterPosition])
​
  //para o clique longo
 binding.root.setOnLongClickListener {
    //chame o método da interface...
    listener.onItemLongClickListener(lista[adapterPosition])
    true //retorna um boolean, necessário para o clique longo
 }
 }
}

3. A Activity implementa a Interface

Quem é familiarizado com o desenvolvimento Android em Java já conhece esse "padrão" de projeto: a Activity que mantém a RecyclerView implementa a interface do Listener (existe outra maneira de se fazer isso no Kotlin, por meio de uma object expression).

class MainActivity : AppCompatActivity(), ClickItemTarefaListener { 
  // corpo da classe
 }

4. Passar a MainActivity como parâmetro para o construtor do Adapter usando this

Ao instanciar o adapter, incluímos uma referência à própria Activity como o parâmetro listener:

class MainActivity : AppCompatActivity(), ClickItemTarefaListener {
​
  private lateinit var binding: DrawerMenuBinding
 // instanciando o adapter com a Activity como listener
  private val adapter = TarefaAdapter(listener = this)
  private val rvList: RecyclerView by lazy {
    binding.drawerInclude.mainRecyclerview
 }

5. Sobrescrever os métodos da interface na MainActivity

E, finalmente, precisamos implementar e sobrescrever os métodos declarados na interface, no corpo da Activity:

override fun onItemClickListener(tarefa: Tarefa) {
  //faça alguma coisa depois do clique curto
}
​
override fun onItemLongClickListener(tarefa: Tarefa) {
  //faça outra coisa ao receber um clique longo
}


E pronto! Agora é possível reconhecer os cliques curtos e longos nos itens da RecyclerView. A partir dessa implementação, é possível programar outros comportamentos, inclusive acessando componentes internos do item (como, por exemplo, um checkbox ou um spinner)


🚀 Um exemplo prático

Vou utilizar como exemplo o projeto inspirado pelo módulo Conceitos de Navegação, Aparência e Estilo de Aplicativos Android (instrutor Igor Ferrani) no everis Kotlin Bootcamp aqui da DIO. Você pode baixar o projeto no meu repositório ou seguir o passo-a-passo em qualquer projeto seu que empregue RecyclerView.

💻 Repositório no github: https://github.com/chicorasia/bootcamp-lista-tarefas

Use o commit 95d7618 e a branch recyclerview .

📼 Confira o passo-a-passo no vídeo: 💊 Pílula de Kotlin - RecyclerView: capture cliques curtos e longos por meio de uma Interface no Android com Kotlin


🏆 Conclusão

Nesse artigo nós vimos uma maneira de se capturar cliques longos e curtos em itens de um RecyclerView no Android com Kotlin, por meio da criação de uma interface Listener e sua implementação na MainActivity.

Há outras maneiras de organizar essa solução, por exemplo, usando object declaration e classes anônimas, que são facilidades da linguagem Kotlin. Mas essa implementação será a base para resolver outros comportamentos, como os cliques nos componentes internos dos itens, arrastar os elementos e usar os swipes para esquerda e direita para manipular os itens.


📷

Ilustração por undraw.co

0
5

Comentários (0)

Arquiteto, urbanista, desenvolvedor Java & Android e criador em chefe na chicorialabs.com.br

Brasil