RecyclerViewはItemTouchHelperを使用してインタラクティブなアニメーションを実現します



Recyclerview Use Itemtouchhelper Achieve Interactive Animation



上記はアイテムの上下ドラッグと左右のスライド効果を行いましたが、現在のアイテムのアニメーション効果のみで、以下は他のアイテムとの相互作用の効果を完了し続けます。

1.上下にドラッグするときに他のアイテムと位置を交換します

1)原則

実際、ItemTouchHelper.Callback自体には2つのアイテムを交換する機能はありませんが、RecyclerViewには、アイテムがドラッグされたときに現在のアイテムを別のアイテムのデータ位置と交換し、RecyclerViewのnotifyItemMoved()メソッドを呼び出して更新することができます。レイアウトと同時に、RecyclerViewにはアイテムアニメーションが付属しているため、上記の操作を完了することができます。



2)実装

アイテムのドラッグはItemTouchHelper.Callbackでリッスンされ、データ交換処理はアダプターで実行されます。結合を減らすには、最初にインターフェースを作成します。

public interface ItemMoveListener { boolean onItemMove(int fromPosition, int toPosition) }Copy code

インターフェイスはアダプタによって実装されます



public class ItemTouchHelperAdapter extends RecyclerView.Adapter<ItemTouchHelperAdapter.ItemTouchHelperViewHolder> implements ItemMoveListener{ ... @Override public boolean onItemMove(int fromPosition, int toPosition) { //1, exchange data Collections.swap(mData, fromPosition, toPosition) //2, refresh notifyItemMoved(fromPosition, toPosition) return true } }Copy code

インターフェースは、ItemTouchHelper.Callbackが作成されたときに渡され、onMove()で呼び出されます。

public class MyItemTouchHelperCallback extends ItemTouchHelper.Callback { ItemMoveListener mItemMoveListener public MyItemTouchHelperCallback(ItemMoveListener itemMoveListener) { mItemMoveListener = itemMoveListener } ... /** * Triggered when item drags and moves * * @param recyclerView * @param viewHolder viewHolder of the currently dragged item * @param targetViewHolder The viewHolder of another item below the currently dragged item * @return */ @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder targetViewHolder) { return mItemMoveListener.onItemMove(viewHolder.getAdapterPosition(), targetViewHolder.getAdapterPosition()) } }Copy code

3)効果:

2、画面を左右にスライドさせると、他の項目が追加されます。

1)原則

同じように、アイテムが画面からスライドする限り、対応するデータを削除してから、RecyclerViewのnotifyItemRemoved()メソッドを呼び出してレイアウトを更新します。

2)実装

アイテムスライドはItemTouchHelper.Callbackでリッスンされ、データ削除プロセスはアダプターで実行されるため、上記のインターフェイスにメソッドを追加するだけで済みます。



public interface ItemMoveListener { ... boolean onItemRemove(int position) }Copy code

インターフェイスはアダプタによって実装されます

public class ItemTouchHelperAdapter extends RecyclerView.Adapter<ItemTouchHelperAdapter.ItemTouchHelperViewHolder> implements ItemMoveListener{ ... @Override public boolean onItemRemove(int position) { //1, delete data mData.remove(position) //2, refresh notifyItemRemoved(position) return true } }Copy code

インターフェイスは、onSwiped()のItemTouchHelper.Callbackで呼び出されます。

/** * Triggered when the item slides out (the vertical list is sideways and the horizontal list is vertical) * * @param viewHolder * @param direction direction of sliding */ @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { mItemMoveListener.onItemRemove(viewHolder.getAdapterPosition()) }Copy code

3)効果:

これでほとんどのエフェクトが実装され、その後に詳細な処理が続きます。

3.インタラクション中の背景の変化

1)原則

アイテムをドラッグまたはスキッドすると背景色が変更され、アクションが終了すると背景色が復元されます。 ItemTouchHelper.Callbackには、onSelectedChanged()とclearView()の2つの状態に対応する正確に2つのメソッドがあります。

2)実装

/** * Triggered when item is dragged or skided * * @param viewHolder * @param actionState The current state of the item */ @Override public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { super.onSelectedChanged(viewHolder, actionState) / / Whether it is dragging or sliding, the background color will change if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) viewHolder.itemView.setBackgroundColor(viewHolder.itemView.getContext().getResources().getColor(android.R.color.darker_gray)) } /** * Triggered when the item's interactive animation ends * * @param recyclerView * @param viewHolder */ @Override public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { super.clearView(recyclerView, viewHolder) viewHolder.itemView.setBackgroundColor(viewHolder.itemView.getContext().getResources().getColor(android.R.color.white)) }Copy code

3)効果

4、左右にスライドしたときのアイテムのグラデーション

1)分析と実装

最初の写真では、アイテムをスキッドアウトすると、アイテムの透明度が徐々に明るくなり、高さが徐々に減少していることがわかります。実際、ItemTouchHelper.Callbackで、アイテムに2種類の属性アニメーションを実行させます。アイテムをドラッグまたはスワイプしたときにディスプレイスメントの変更を取得する方法、つまりonChildDraw()メソッドがあるため、非常に簡単に実行できます。次のコード実装を参照してください。

@Override public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { / / This code is the implementation of item drag and slide effects, so this sentence can not be omitted super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive) //We only need to reduce the value of transparency and height when sliding left and right (1 --> 0) if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) { float value = 1 - Math.abs(dX) / viewHolder.itemView.getWidth() viewHolder.itemView.setAlpha(value) viewHolder.itemView.setScaleY(value) } }Copy code

2)効果(欠陥あり)

スライドの過程で、アイテムが徐々に透明になり、収縮することがわかります。しかし、私は明らかに2つを削除し、結果リストには2つの空白データがいくつありますか。これが理由です?

3)修理

実際、上の図には2つ以下の空白データがあります。これらは通常のデータであり、表示できません。これは、RecyclerViewアイテム(itemView)がオーバーライドされ、itemViewがonChildDraw()メソッドで透過的であるためです。そしてズームアウトすると、リストに固定されているitemViewはごくわずかです。 2つの透明で縮小されたitemViewを再度使用すると、以前に設定された透明度と高さの比率はすでに0になっているため、これが発生し、解決策は非常に簡単です。アイテムが削除されている限り、itemViewの透明度と高さの比率を元に戻します。 、コードは次のとおりです。

/** * Triggered when the item's interactive animation ends * * @param recyclerView * @param viewHolder */ @Override public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { super.clearView(recyclerView, viewHolder) ... viewHolder.itemView.setAlpha(1) viewHolder.itemView.setScaleY(1) }Copy code

4)効果(完璧)

この時点で、すべての初期相互作用が実装されています。

最後に、デモリンクを添付します。

github.com/GitLqr/Mate…