Arraste e deslize o dedo no RecyclerView. Parte 1: ItemTouchHelper

Arraste e deslize o dedo no RecyclerView. Parte 1: ItemTouchHelper


Existem muitos tutoriais, bibliotecas e implementações de arrastar e soltar e deslizar para dispensar no Android usando o RecyclerView. A maioria deles ainda usa o View.OnDragListener e a abordagem SwipeToDismiss , obsoleta , desenvolvida por Roman Nurik. Embora métodos novos e mais eficazes já estejam disponíveis. Muito poucos usam as APIs mais recentes, geralmente usando GestureDetectors e onInterceptTouchEvent ou outras implementações mais complexas. Na verdade, existe uma maneira muito simples de adicionar essas funções ao RecyclerView . Isso requer apenas uma classe, que também faz parte da Biblioteca de Suporte do Android.


ItemTouchHelper


O ItemTouchHelper é um utilitário poderoso que cuida de tudo que você precisa para adicionar funções de arrastar e soltar e deslizar para dispensar no RecyclerView . Esse utilitário é uma subclasse de RecyclerView.ItemDecoration , facilitando a adição a quase todos os LayoutManager e adaptadores existentes. Ele também funciona com animação de elementos e fornece a capacidade de arrastar e soltar elementos de um tipo para outro lugar na lista e muito mais. Neste artigo, demonstrarei uma implementação simples do ItemTouchHelper . Posteriormente, como parte desta série de artigos, expandiremos o escopo e consideraremos outras opções.


Nota Deseja ver o resultado imediatamente? Confira o Github: Android-ItemTouchHelper-Demo . O primeiro commit está relacionado a este artigo. O arquivo .apk demonstração pode ser baixado aqui .


Exemplo


Personalização


Primeiro, precisamos configurar o RecyclerView . Se você ainda não o fez, inclua a dependência do RecyclerView em seu arquivo build.gradle .


 compile 'com.android.support:recyclerview-v7:22.2.0' 

ItemTouchHelper funcionará com praticamente qualquer RecyclerView.Adapter e LayoutManager , mas este artigo é baseado em exemplos usando esses arquivos .


Usando ItemTouchHelper e ItemTouchHelper.Callback


Para usar o ItemTouchHelper , você precisa criar um ItemTouchHelper.Callback . Esta é uma interface que permite rastrear as ações de movimento ( eng. Mover) e deslizar ( eng. Deslizar). Além disso, aqui você pode controlar o estado do componente de view selecionado e substituir a animação padrão. Há uma classe auxiliar que você pode usar se desejar usar a implementação básica, SimpleCallback . Mas, para entender como isso funciona na prática, faremos tudo sozinhos.


As principais funções da interface que devemos redefinir para incluir a funcionalidade básica de arrastar e soltar e deslizar para dispensar :


 getMovementFlags(RecyclerView, ViewHolder) onMove(RecyclerView, ViewHolder, ViewHolder) onSwiped(ViewHolder, int) 

Também usaremos vários métodos auxiliares:


 isLongPressDragEnabled() isItemViewSwipeEnabled() 

Vamos considerá-los um por um.


 @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END; return makeMovementFlags(dragFlags, swipeFlags); } 

ItemTouchHelper facilita a determinação da direção de um evento. Você precisa substituir o método getMovementFlags() para indicar quais instruções para arrastar e soltar serão suportadas. Para criar sinalizadores de retorno, use o método auxiliar ItemTouchHelper.makeMovementFlags(int, int) . Neste exemplo, permitimos arrastar e soltar nas duas direções.


 @Override public boolean isLongPressDragEnabled() { return true; } 

ItemTouchHelper pode ser usado apenas para arrastar e soltar sem a funcionalidade de furto (ou vice-versa), portanto, você deve especificar exatamente quais recursos devem ser suportados. O método isLongPressDragEnabled() deve retornar true para suportar arrastar e soltar após um longo clique no elemento RecyclerView . Como alternativa, você pode chamar o ItemTouchHelper.startDrag(RecyclerView.ViewHolder) para começar a arrastar manualmente. Consideraremos essa opção mais tarde.


 @Override public boolean isItemViewSwipeEnabled() { return true; } 

Para ativar o chicote após tocar em qualquer lugar do componente de view , basta retornar true partir do método isItemViewSwipeEnabled() . Como alternativa, você pode chamar o ItemTouchHelper.startSwipe(RecyclerView.ViewHolder) para iniciar o furto manualmente.


Os dois métodos a seguir, onMove() e onSwiped() , são necessários para notificá-lo sobre atualizações de dados. Portanto, primeiro criaremos uma interface que permitirá que esses eventos sejam transmitidos ao longo da cadeia de chamadas.


ItemTouchHelperAdapter.java


 public interface ItemTouchHelperAdapter { void onItemMove(int fromPosition, int toPosition); void onItemDismiss(int position); } 

A maneira mais fácil de fazer isso é fazer com que o RecyclerListAdapter implemente o ouvinte.


 public class RecyclerListAdapter extends RecyclerView.Adapter<ItemViewHolder> implements ItemTouchHelperAdapter { // ...   [](https://gist.github.com/iPaulPro/2216ea5e14818056cfcc#file-recyclerlistadapter-java) @Override public void onItemDismiss(int position) { mItems.remove(position); notifyItemRemoved(position); } @Override public boolean onItemMove(int fromPosition, int toPosition) { if (fromPosition < toPosition) { for (int i = fromPosition; i < toPosition; i++) { Collections.swap(mItems, i, i + 1); } } else { for (int i = fromPosition; i > toPosition; i--) { Collections.swap(mItems, i, i - 1); } } notifyItemMoved(fromPosition, toPosition); return true; } 

É muito importante chamar os notifyItemRemoved() e notifyItemMoved() para que o adaptador veja as alterações. Deve-se notar também que alteramos a posição do elemento toda vez que o componente view é alterado para um novo índice, e não no final do movimento (o evento “drop”) .


Agora podemos voltar a criar SimpleItemTouchHelperCallback , pois ainda precisamos substituir os onMove() e onSwiped() . Primeiro adicione o construtor e o campo para o adaptador:


 private final ItemTouchHelperAdapter mAdapter; public SimpleItemTouchHelperCallback( ItemTouchHelperAdapter adapter) { mAdapter = adapter; } 

Redefina os eventos restantes e relate isso ao adaptador:


 @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition()); return true; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { mAdapter.onItemDismiss(viewHolder.getAdapterPosition()); } 

Como resultado, a classe Callback deve se parecer com isso:


 public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback { private final ItemTouchHelperAdapter mAdapter; public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) { mAdapter = adapter; } @Override public boolean isLongPressDragEnabled() { return true; } @Override public boolean isItemViewSwipeEnabled() { return true; } @Override public int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder) { int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END; return makeMovementFlags(dragFlags, swipeFlags); } @Override public boolean onMove(RecyclerView recyclerView, ViewHolder viewHolder, ViewHolder target) { mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition()); return true; } @Override public void onSwiped(ViewHolder viewHolder, int direction) { mAdapter.onItemDismiss(viewHolder.getAdapterPosition()); } } 

Quando o retorno de chamada está pronto, podemos criar um ItemTouchHelper e chamar o attachToRecyclerView(RecyclerView) (por exemplo, em MainFragment.java ):


 ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(adapter); ItemTouchHelper touchHelper = new ItemTouchHelper(callback); touchHelper.attachToRecyclerView(recyclerView); 

Depois de iniciar, você deve obter algo como o seguinte:


Resultado


Conclusão


Esta é a implementação mais simplificada do ItemTouchHelper . No entanto, você pode perceber que não precisa usar uma biblioteca de terceiros para implementar as ações padrão de arrastar e soltar e deslizar para dispensar no RecyclerView . Na próxima parte, prestaremos mais atenção à aparência dos elementos no momento do arrastar e soltar.


Código fonte


Criei um projeto no GitHub para demonstrar o que é abordado nesta série de artigos: Android-ItemTouchHelper-Demo . O primeiro commit está relacionado principalmente a essa parte e um pouco à segunda .


→ Arraste e deslize o dedo no RecyclerView. Parte 2: arraste e solte controladores, grades e animações personalizadas

Source: https://habr.com/ru/post/pt427681/


All Articles