Alex é instrutor e desenvolvedor e possui experiência em Java, Kotlin, Android. Atualmente cria conteúdo no canal https://www.youtube.com/@AlexFelipeDev.
Inscreva-se em nossa Newsletter
Fique por dentro de conteúdos, insights e oportunidades do universo tech. Receba novidades e lançamentos direto no seu e-mail.
Vou personalizar uma ListView no Android para que cada item da lista tenha seu próprio visual, dando uma maior flexibilidade para o desenvolvimento minha app.
No artigo sobre como criar listas com o ListView que eu escrevi anteriormente, vimos como é possível criar uma lista bem básica no Android. O resultado da lista criada foi:
Mas pensando bem, não era exatamente uma lista assim que eu queria... Em outras palavras, seria melhor se cada item tivesse um layout e um design da minha preferência como, por exemplo, esse item que eu criei:
Bem... Lembra como fazíamos para adicionar um item na lista? Nós utilizamos a classe ArrayAdapter do Android que era responsável em adaptar itens em uma ListView!
Mas ela é uma implementação já pronta do Android e não conseguimos manipular esse adapter da forma que desejamos...
E agora? Bom, se não podemos modificar a implementação do Android, precisamos implementar a nossa! E como podemos implementar um adapter nosso?
Criando nosso próprio Adapter
Para a nossa felicidade, o Android nos fornece a classe BaseAdapter que permite a criação de um adapter personalizado! Então vamos criar uma nova classe que representará o nosso novo adapter e vamos estender a classe BaseAdapter:
Observe os 3 primeiros métodos: getCount(), getItem(int position), getItemId(int position). Perceba que são métodos relacionados a uma lista! Para implementá-los da maneira correta, precisamos de uma lista dentro do nosso adapter.
Lembra que enviávamos a nossa lista via construtor no ArrayAdapter? Faremos o mesmo no nosso adapter para que possamos implementar esses métodos da maneira esperada:
Agora podemos implementar os nossos métodos! Vamos começar pelo getCount(). O próprio método já diz o que ele faz: conta quantos itens existem na lista. Ou seja, o tamanho da lista.
Agora vamos para o getItem(int position). Veja que ele quer saber um item a partir de uma posição. Isso é fácil! Basta apenas retornamos por meio do método get() mandando a posição:
Vejamos o próximo: getItemId(int position). Esse método espera saber qual é o id do objeto que está sendo buscado. Porém, se verificarmos a nossa classe que representa um curso:
Repare que agora ele retorna uma View, ou seja, esse é o método responsável pela construção de cada item! O que precisamos para implementá-lo?
Inicialmente, precisamos, de alguma forma, pegar a View que representa o nosso layout personalizado. Afinal é ela que queremos apresentar na nossa lista!
Mas, para pegar uma View, nós precisamos de uma Activity e a nossa classe, além de não ser uma Activity, não possui uma Activity.
E agora? O que faremos? Se dermos uma olhada na forma que fizemos para instanciar o ArrayAdapter anteriormente:
Veja que estamos passando passando o parâmetro this que representa o objeto da própria Activity que está fazendo a chamada. Precisamos receber também essa Activity via construtor:
Perceba que utilizamos o parent que vem como parâmetro do método getView(). Mas o que ele representa? Como podemos ver, o parent é a própria ViewGroup, ou seja, o layout pai ao qual iremos adicionar a nossa lista, por isso enviamos ele.
Além disso, ainda existe o último parâmetro que recebe um valor booleano, esse parâmetro indica se queremos criar, nesse exato momento a View.
Mas, não fizemos nenhum tipo de alteração como adicionar as informações do curso, por isso mandamos o false. Dessa forma, podemos associar tudo que queremos e só depois ele criará de fato a View :)
Certo, pegamos a nossa View e agora precisamos de um curso, certo? Mas qual curso?
Veja que, ainda existe um parâmetro no getView() que é o position, ou seja, é justamente nessa posição que devemos pegar o elemento da lista que foi passada, nesse nosso caso, o curso:
Observe que não foi apresentada a implementação do método todosOsCursos() justamente para ser mais objetivo na implementação do componente ListView. Compreenda esse método como um acesso aos dados qualquer, seja uma lista estática, banco de dados ou qualquer meio que devolva uma lista de cursos.
Agora se testarmos a nossa app:
Adicionando uma imagem diferente para cada item da lista
A nossa lista mudou, porém ainda há uma coisa bem bizarra: no curso de Java temos a imagem do Java, no de HTML também, e no de Android também! E não era isso que nós queríamos!
Nós queremos que, para cada curso, seja usada uma imagem que identifique-o. Por exemplo: curso de Java imagem de Java, curso de HTML, imagem de HTML e assim por diante. O que será que erramos?
Vejamos como está sendo inserida a imagem no getView() do nosso adapter:
Observe que estamos setando a mesma imagem para todos os elementos da lista! Precisamos de alguma informação do curso para sabermos a que ele se refere!
Atualmente, não temos nenhum tipo de informação para categorizar os nossos cursos, então que tal criarmos um enum para isso?
publicenumCategoria {
JAVA, HTML, ANDROID
}
E agora adicionamos um enum para a nossa classe curso:
Essa solução com esse tanto de if e else funciona, porém não é uma boa prática! Nesse post eu detalho um dos grandes problemas que temos com esse tipo de solução e como podemos resolver de uma maneira mais elegante.
Adicionamos as nossas condições para setar as imagens, então agora vamos testar e ver o resultado:
Excelente! A nossa lista personalizada foi criada conforme o esperado!
Aprendendo um pouco mais
Embora tenhamos aprendido a implementar e personalizar uma ListView ainda existe mais um detalhe importante durante a implementação de um Adapter que é justamente o padrão ViewHolder.
Não será explicado sobre esse padrão, entretanto, o Matheus escreveu um excelente post explicando a teoria e como é possível implementar o ViewHolder na ListView.
Resumo
Vimos que, para criar uma lista personalizada, nós precisamos fazer uma implementação nossa estendo da classe BaseAdapter que permite a criação de um adapter personalizado.
Vimos também que temos que especificar tudo que iremos adicionar na lista, como por exemplo, as informações do curso para sua View específica.
Além disso, vimos que podemos declarar condições no método getView() para adicionar conteúdo diferente de acordo com algum critério, como foi o caso da imagem específica para cada curso.
Código fonte
Caso tiver dúvidas ou simplesmente quiser consultar o código fonte do projeto utilizado como exemplo, fique à vontade de dar uma olhada no github. Lembrando que para essa etapa do projeto eu fiz uso da branch lista-personalizada.
E aí, gostou de criar uma lista própria? Quer aprender mais dicas sobre o Android? Que tal conhecer a formação Android.