Aqui você vê as diferenças entre duas revisões dessa página.
Ambos lados da revisão anterior Revisão anterior Próxima revisão | Revisão anterior | ||
android-recycler-view [2019/10/04 11:11] forfs [Concluindo a configuração do RecyclerView e teste] |
android-recycler-view [2019/10/05 09:23] (atual) forfs |
||
---|---|---|---|
Linha 1: | Linha 1: | ||
====== Crie listas com RecyclerView ====== | ====== Crie listas com RecyclerView ====== | ||
- | |||
- | //Artigo em construção. Enquanto isso, você pode seguir [[https://medium.com/android-dev-br/listas-com-recyclerview-d3f41e0d653c|esse artigo]].// | ||
Em aplicativos [[Android]], é comum criar telas com listagens de diversas formas possíveis: horizontalmente, verticalmente, em forma de grade, entre outros exemplos. Existem casos que a quantidade de itens é **tão grande** que o aplicativo demora **vários segundos** para renderizar-los, causando **desconforto** no usuário. Dessa forma, entra em cena o //**RecyclerView**//, componente padrão de //layout// de listagens do [[Android Studio]] para uso no desenvolvimento nativo de aplicativos [[Android]], o qual utiliza itens "**recicláveis**" na respectiva //[[https://developer.android.com/reference/android/view/View|View]]// a ser desenvolvida. | Em aplicativos [[Android]], é comum criar telas com listagens de diversas formas possíveis: horizontalmente, verticalmente, em forma de grade, entre outros exemplos. Existem casos que a quantidade de itens é **tão grande** que o aplicativo demora **vários segundos** para renderizar-los, causando **desconforto** no usuário. Dessa forma, entra em cena o //**RecyclerView**//, componente padrão de //layout// de listagens do [[Android Studio]] para uso no desenvolvimento nativo de aplicativos [[Android]], o qual utiliza itens "**recicláveis**" na respectiva //[[https://developer.android.com/reference/android/view/View|View]]// a ser desenvolvida. | ||
Linha 102: | Linha 100: | ||
{{ :recyclerview-example-1.png?direct |}} | {{ :recyclerview-example-1.png?direct |}} | ||
- | Para fins didáticos, excluiremos o //TextView// presente no //layout// e adicionaremos o **RecyclerView** ao //layout//. Para isso, basta selecionar o componente **RecyclerView** em //Palette// e arrastar para a tela branca. | + | Para fins didáticos, excluiremos o //TextView// presente no //layout// e adicionaremos o //**RecyclerView**// ao //layout//. Para isso, basta selecionar o componente //**RecyclerView**// em //Palette// e arrastar para a tela branca. |
{{ :recyclerview-example-2-edit.png?direct |}} | {{ :recyclerview-example-2-edit.png?direct |}} | ||
- | Será aberto um aviso para confirmar a importação da biblioteca referente ao **RecyclerView**. Basta clicar em **OK** para continuar. | + | Será aberto um aviso para confirmar a importação da biblioteca referente ao //**RecyclerView**//. Basta clicar em **OK** para continuar. |
{{ :recyclerview-example-3.png?direct |}} | {{ :recyclerview-example-3.png?direct |}} | ||
- | Dessa forma, o **RecyclerView** será importado ao projeto e adicionado ao seu //layout// que está conectado à sua //Activity//. Conectando as //constraints// às laterais de sua tela branca e inserindo a //string// **recyclerViewExemplo** como //id// do **RecyclerView** adicionado, teremos como resultado a imagem abaixo. | + | Dessa forma, o //**RecyclerView**// será importado ao projeto e adicionado ao seu //layout// que está conectado à sua //Activity//. Conectando as //constraints// às laterais de sua tela branca e inserindo a //string// **recyclerViewExemplo** como //id// do //**RecyclerView**// adicionado, teremos como resultado a imagem abaixo. |
{{ :recyclerview-example-4.png?direct |}} | {{ :recyclerview-example-4.png?direct |}} | ||
Linha 143: | Linha 141: | ||
==== Instanciando o LayoutManager e vinculando-o ao RecyclerView ==== | ==== Instanciando o LayoutManager e vinculando-o ao RecyclerView ==== | ||
- | Nesse passo, primeiramente iremos referenciar o **RecyclerView** no código java através da classe representativa do componente e do método //findViewById//. | + | Nesse passo, primeiramente iremos referenciar o //**RecyclerView**// no código java através da classe representativa do componente e do método //findViewById//. |
<code java MainActivity.java> | <code java MainActivity.java> | ||
Linha 172: | Linha 170: | ||
- | Posteriormente, iremos instanciar o //LayoutManager// configurando-o da forma que preferirmos e inserindo no **RecyclerView**. Nesse exemplo, configuraremos o //LayoutManager// como sendo do tipo //LinearLayoutManager// com orientação vertical. | + | Posteriormente, iremos instanciar o //LayoutManager// configurando-o da forma que preferirmos e inserindo no //**RecyclerView**//. Nesse exemplo, configuraremos o //LayoutManager// como sendo do tipo //LinearLayoutManager// com orientação vertical. |
<code java MainActivity.java> | <code java MainActivity.java> | ||
Linha 225: | Linha 223: | ||
**Lembre-se**: o //layout// mais **externo** deve ter o atributo //layout_height// com o valor **//wrap_content//**. Caso não seja feita essa verificação, há possibilidade dos itens possuírem um tamanho muito grande para o tamanho da tela. | **Lembre-se**: o //layout// mais **externo** deve ter o atributo //layout_height// com o valor **//wrap_content//**. Caso não seja feita essa verificação, há possibilidade dos itens possuírem um tamanho muito grande para o tamanho da tela. | ||
- | **Dica**: utilizar //LinearLayout// ao invés de //ConstraintLayout// traz resultados melhores nessa parte da configuração do **RecyclerView**, mas, como dito, por questões didáticas, será mantido o uso do segundo. | + | **Dica**: utilizar //LinearLayout// ao invés de //ConstraintLayout// traz resultados melhores nessa parte da configuração do //**RecyclerView**//, mas, como dito, por questões didáticas, será mantido o uso do segundo. |
{{ ::recyclerview-example-7.png?direct |}} | {{ ::recyclerview-example-7.png?direct |}} | ||
Linha 500: | Linha 498: | ||
</code> | </code> | ||
- | Após criar a classe base para cada item da lista, voltaremos ao //Adapter// e criaremos como atributo dentro dele uma lista de //Item//, além de um construtor que recebe como atributo também uma lista de //Item//. O construtor, nesse caso, serve para que, durante a configuração do **RecyclerView**, o //Adapter// saiba quais itens serão apresentados na tela do aplicativo. | + | Após criar a classe base para cada item da lista, voltaremos ao //Adapter// e criaremos como atributo dentro dele uma lista de //Item//, além de um construtor que recebe como atributo também uma lista de //Item//. O construtor, nesse caso, serve para que, durante a configuração do //**RecyclerView**//, o //Adapter// saiba quais itens serão apresentados na tela do aplicativo. |
<code java AdapterExemplo.java> | <code java AdapterExemplo.java> | ||
Linha 539: | Linha 537: | ||
</code> | </code> | ||
- | O primeiro método que podemos configurar é o //getItemCount//, que retornará ao **RecyclerView** o número de itens da lista a ser apresentada. No nosso exemplo, será justamente o tamanho da lista que o //Adapter// possui como atributo. | + | O primeiro método que podemos configurar é o //getItemCount//, que retornará ao //**RecyclerView**// o número de itens da lista a ser apresentada. No nosso exemplo, será justamente o tamanho da lista que o //Adapter// possui como atributo. |
<code java AdapterExemplo.java> | <code java AdapterExemplo.java> | ||
Linha 681: | Linha 679: | ||
==== Concluindo a configuração do RecyclerView e teste ==== | ==== Concluindo a configuração do RecyclerView e teste ==== | ||
- | Neste momento, as classes //Adapter// e //ViewHolder// estão configuradas. Agora, precisaremos voltar para a //Activity// principal de nosso projeto e configurar, finalmente, o tão amado **RecyclerView**. Primeiramente, será preciso de um banco de dados de itens para serem apresentados na lista. Numa aplicação real, essa lista será obtida através de um banco de dados na nuvem ou baixados através de uma API presente num servidor da aplicação. Como aqui se trata de um exemplo, será criado um banco de dados //hardcoded//. | + | Neste momento, as classes //Adapter// e //ViewHolder// estão configuradas. Agora, precisaremos voltar para a //Activity// principal de nosso projeto e configurar, finalmente, o tão amado //**RecyclerView**//. Primeiramente, será preciso de um banco de dados de itens para serem apresentados na lista. Numa aplicação real, essa lista será obtida através de um banco de dados na nuvem ou baixados através de uma API presente num servidor da aplicação. Como aqui se trata de um exemplo, será criado um banco de dados //hardcoded//. |
<code java MainActivity.java> | <code java MainActivity.java> | ||
Linha 759: | Linha 757: | ||
</code> | </code> | ||
- | Agora, devemos instanciar um objeto do tipo //AdapterExemplo// que criamos na seção anterior, inserindo como atributo de seu construtor a lista //listaItens//. Após a instanciação, podemos vincular o //Adapter// ao nosso **RecyclerView**. | + | Agora, devemos instanciar um objeto do tipo //AdapterExemplo// que criamos na seção anterior, inserindo como atributo de seu construtor a lista //listaItens//. Após a instanciação, podemos vincular o //Adapter// ao nosso //**RecyclerView**//. |
<code java MainActivity.java> | <code java MainActivity.java> | ||
Linha 846: | Linha 844: | ||
Ao executar o aplicativo, podemos ver o resultado de toda a configuração realizada. | Ao executar o aplicativo, podemos ver o resultado de toda a configuração realizada. | ||
+ | {{ :recyclerview-example-15.png?direct |}} | ||
+ | Pode-se adicionar mais itens até que seja necessário rolar a lista para baixo. **Não importa** a quantidade de itens que seja colocado, mesmo sendo **10**, **100** ou **1000**: o aplicativo executará **sem travamentos**. | ||
+ | |||
+ | {{ :recyclerview-example-16.png?direct |}} | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== Complementos ===== | ||
+ | |||
+ | ==== Evento de clique ==== | ||
+ | |||
+ | Além da configuração de um //**RecyclerView**// para mostrar itens na tela do usuário, pode-se também configurar eventos de clique em cada item da lista. Isso é muito útil para aplicativos de redes sociais, //marketplaces//, entre vários outros exemplos. | ||
+ | |||
+ | Para isso, deve-se primeiro incluir essa classe dentro de seu projeto. | ||
+ | |||
+ | <code java RecyclerItemClickListener.java> | ||
+ | |||
+ | package com.exemplo.recyclerview; | ||
+ | |||
+ | import android.content.Context; | ||
+ | import android.support.v7.widget.RecyclerView; | ||
+ | import android.view.GestureDetector; | ||
+ | import android.view.MotionEvent; | ||
+ | import android.view.View; | ||
+ | import android.widget.AdapterView; | ||
+ | |||
+ | /** | ||
+ | * Created by Jamilton on 01/11/2017. | ||
+ | * RecyclerView não possui o método OnItemClickListener para identificar o clique do item. | ||
+ | * Você precisa escrever sua própria classe que se estende RecyclerView.OnItemTouchListener. | ||
+ | */ | ||
+ | |||
+ | public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener { | ||
+ | |||
+ | private OnItemClickListener mListener; | ||
+ | GestureDetector mGestureDetector; | ||
+ | |||
+ | @Override | ||
+ | public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { | ||
+ | View childView = rv.findChildViewUnder(e.getX(), e.getY()); | ||
+ | if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) { | ||
+ | mListener.onItemClick(childView, rv.getChildAdapterPosition(childView)); | ||
+ | return true; | ||
+ | } | ||
+ | return false; | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public void onTouchEvent(RecyclerView rv, MotionEvent e) { | ||
+ | |||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { | ||
+ | |||
+ | } | ||
+ | |||
+ | public interface OnItemClickListener extends AdapterView.OnItemClickListener { | ||
+ | public void onItemClick(View view, int position); | ||
+ | |||
+ | public void onLongItemClick(View view, int position); | ||
+ | } | ||
+ | |||
+ | public RecyclerItemClickListener(Context context, final RecyclerView recyclerView, OnItemClickListener listener) { | ||
+ | mListener = listener; | ||
+ | mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { | ||
+ | @Override | ||
+ | public boolean onSingleTapUp(MotionEvent e) { | ||
+ | return true; | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public void onLongPress(MotionEvent e) { | ||
+ | View child = recyclerView.findChildViewUnder(e.getX(), e.getY()); | ||
+ | if (child != null && mListener != null) { | ||
+ | mListener.onLongItemClick(child, recyclerView.getChildAdapterPosition(child)); | ||
+ | } | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | Após isso, dentro de sua //Activity//, configure o //**RecyclerView**// com o pedaço de código abaixo. | ||
+ | |||
+ | <code java> | ||
+ | |||
+ | recyclerViewExemplo.addOnItemTouchListener(new RecyclerItemClickListener( | ||
+ | this, | ||
+ | recyclerViewExemplo, | ||
+ | new RecyclerItemClickListener.OnItemClickListener() { | ||
+ | @Override | ||
+ | public void onItemClick(View view, int position) { | ||
+ | Item item = listaItens.get(position); | ||
+ | Toast.makeText( | ||
+ | MainActivity.this, | ||
+ | "Você clicou no item número " + item.getTextNumeroItem(), | ||
+ | Toast.LENGTH_SHORT | ||
+ | ).show(); | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public void onLongItemClick(View view, int position) { | ||
+ | |||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public void onItemClick(AdapterView<?> parent, View view, int position, long id) { | ||
+ | |||
+ | } | ||
+ | } | ||
+ | )); | ||
+ | |||
+ | </code> | ||
+ | |||
+ | Após essa configuração, a cada vez que clicar em um item da lista, será mostrado uma mensagem com o atributo "número" do item. | ||
+ | |||
+ | ==== Animações ==== | ||
+ | |||
+ | É possível criar animações no momento que cada item da lista é carregado na tela do usuário. Você pode implementar isso [[https://medium.com/better-programming/android-recyclerview-with-beautiful-animations-5e9b34dbb0fa|seguindo esse tutorial]]. | ||
+ | |||
+ | ==== Exemplos ==== | ||
+ | |||
+ | * Um //chat// entre duas pessoas pode (e deve) ser implementado utilizando um //**RecyclerView**//. A ideia é que, no método //onCreateViewHolder//, seja feito uma verificação e decidido se o balão será referente ao usuário que utiliza o aplicativo (balão verde) ou ao outro usuário (balão branco), mudando o //layout// base em cada situação. | ||
+ | |||
+ | {{ :recyclerview-example-17.png?direct |}} | ||
+ | |||
+ | * Um aplicativo de gerenciamento de despesas **tem obrigação** de ter um histórico de gastos. Um exemplo disso é o aplicativo [[https://www.organizze.com.br/|Organizze]], que consegue mostrar de forma clara todos os seus gastos. Ao desenvolver um aplicativo semelhante que necessita desse histórico, o uso do //**RecyclerView**// é uma boa opção. | ||
+ | |||
+ | {{ :recyclerview-example-18.png?direct |}} | ||
---- | ---- | ||
===== Referências externas ===== | ===== Referências externas ===== | ||
+ | Você pode acessar o código completo do exemplo desenvolvido aqui no [[https://github.com/ADA-EC/Wiki|repositório da ADA]] no GitHub. Outros //links// utilizados como base de desenvolvimento desse artigo estão elencados abaixo. | ||
+ | |||
+ | * [[https://www.udemy.com/course/curso-de-desenvolvimento-android-oreo/|Udemy | Desenvolvimento Android Completo - Aprenda a criar 18 Apps]] | ||
+ | * [[https://medium.com/better-programming/android-recyclerview-with-beautiful-animations-5e9b34dbb0fa|Medium | Android RecyclerView with beautiful animations]] | ||
* [[https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView.html|Android Developers | RecyclerView documentation]] | * [[https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView.html|Android Developers | RecyclerView documentation]] | ||
* [[https://developer.android.com/guide/topics/ui/layout/recyclerview|Android Developers | Create a List with RecyclerView]] | * [[https://developer.android.com/guide/topics/ui/layout/recyclerview|Android Developers | Create a List with RecyclerView]] | ||
- | * [[https://www.udemy.com/course/curso-de-desenvolvimento-android-oreo/|Udemy | Desenvolvimento Android Completo - Aprenda a criar 18 Apps]] | + | * [[https://developer.android.com/reference/android/support/v7/widget/RecyclerView.LayoutManager|Android Developers | RecyclerView.LayoutManager]] |
+ | * [[https://developer.android.com/reference/android/widget/Adapter|Android Developers | RecyclerView.Adapter]] | ||
+ | * [[https://developer.android.com/reference/android/support/v7/widget/RecyclerView.ViewHolder|Android Developers | RecyclerView.ViewHolder]] | ||
+ | * [[https://developer.android.com/reference/android/view/ViewGroup|Android Developers | ViewGroup]] | ||
+ | * [[https://developer.android.com/reference/android/view/View|Android Developers | View]] | ||
+ | * [[https://developer.android.com/reference/android/support/v7/widget/LinearLayoutManager|Android Developers | LinearLayoutManager]] | ||
+ | * [[https://developer.android.com/reference/android/support/v7/widget/GridLayoutManager|Android Developers | GridLayoutManager]] | ||
+ | * [[https://developer.android.com/reference/android/support/v7/widget/StaggeredGridLayoutManager|Android Developers | StaggeredGridLayoutManager]] | ||
+ | * [[https://developer.android.com/reference/android/view/LayoutInflater|Android Developers | LayoutInflater]] | ||
+ | * [[https://developer.android.com/reference/android/content/Context|Android Developers | Context]] | ||
+ | * [[https://developer.android.com/reference/java/net/URI|Android Developers | URI]] |