RecyclerViewでドラッグしてスワイプします。 パート1:ItemTouchHelper

RecyclerViewでドラッグしてスワイプします。パート1:ItemTouchHelper







RecyclerViewを使用したAndroidには、多くのチュートリアル、ライブラリ、 ドラッグアンドドロップスワイプして非表示の実装があります。 それらのほとんどは、非推奨のView.OnDragListenerとRoman Nurikが開発したSwipeToDismissアプローチをまだ使用しています。 新しい、より効果的な方法はすでに利用可能ですが。 最新のAPIを使用することはほとんどありません。多くの場合、 GestureDetectors



およびonInterceptTouchEvent



またはその他のより複雑な実装に依存しています。 実際、これらの関数をRecyclerView



に追加する非常に簡単な方法があります。 これには、Androidサポートライブラリの一部でもある1つのクラスのみが必要です。







ItemTouchHelper



ItemTouchHelperは強力なユーティリティであり、 RecyclerView



ドラッグアンドドロップおよびスワイプして 閉じる 機能を追加するために必要なすべてを処理します。 このユーティリティは、 RecyclerView.ItemDecorationのサブクラスであり、既存のほぼすべてのLayoutManager



とアダプターに簡単に追加できます。 また、要素のアニメーションにも対応し、あるタイプの要素をリスト内の別の場所などにドラッグアンドドロップする機能を提供します。 この記事では、 ItemTouchHelper



簡単な実装をItemTouchHelper



ます。 後で、この一連の記事の一部として、範囲を拡大し、他のオプションを検討します。







ご注意 結果をすぐに見たいですか? Github: Android-ItemTouchHelper-Demoをご覧ください。 最初のコミットはこの記事に関連しています。 デモの.apk



ファイルはここからダウンロードできます







例







カスタマイズ



最初にRecyclerView



を設定する必要があります。 まだ行っていない場合は、 build.gradle



ファイルにRecyclerView



依存関係を追加します。







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





ItemTouchHelper



はほぼすべてのRecyclerView.Adapter



およびLayoutManager



で動作しますが、この記事はこれらのファイルを使用した例に基づいています







ItemTouchHelperとItemTouchHelper.Callbackを使用する



ItemTouchHelper



を使用するには、 ItemTouchHelper



を作成する必要があります。 これは、動き( eng。Move )とスワイプ( eng。Swipe )を追跡できるインターフェースです。 さらに、ここでは、選択したview



コンポーネントの状態を制御し、デフォルトのアニメーションをオーバーライドできます。 基本実装SimpleCallbackを使用する場合に使用できるヘルパークラスがあります 。 しかし、これが実際にどのように機能するかを理解するために、私たちはすべて自分で行います。







ドラッグアンドドロップおよびスワイプして閉じるという基本的な機能を含めるために再定義する必要があるインターフェイスの主な機能:







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





また、いくつかのヘルパーメソッドを使用します。







 isLongPressDragEnabled() isItemViewSwipeEnabled()
      
      





それらを一つ一つ考えてみましょう。







 @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



すると、イベントの方向を簡単に判断できます。 getMovementFlags()



メソッドをオーバーライドして、ドラッグアンドドロップする方向がサポートされることを示す必要があります。 リターンフラグを作成するには、ヘルパーメソッドItemTouchHelper.makeMovementFlags(int, int)



ます。 この例では、両方向のドラッグアンドドロップを有効にします。







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





ItemTouchHelper



は、スワイプ機能なしのドラッグアンドドロップ(またはその逆)でのみ使用できるため、サポートする機能を正確に指定する必要があります。 isLongPressDragEnabled()



メソッドは、 RecyclerView



要素を長isLongPressDragEnabled()



後のドラッグアンドドロップをサポートするためにtrue



を返す必要があります。 または、 ItemTouchHelper.startDrag(RecyclerView.ViewHolder)



メソッドを呼び出して、手動でドラッグを開始できます。 このオプションは後で検討します。







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





view



コンポーネント内の任意の場所に触れた後にホイップを有効にするには、 isItemViewSwipeEnabled()



メソッドからtrue



を返すだけです。 または、 ItemTouchHelper.startSwipe(RecyclerView.ViewHolder)



メソッドを呼び出して、スワイプを手動で開始できます。







データの更新を通知するには、次の2つのメソッドonMove()



およびonSwiped()



が必要です。 そのため、最初に、これらのイベントを一連の呼び出しに沿って送信できるようにするインターフェイスを作成します。







ItemTouchHelperAdapter.java







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





これを行う最も簡単な方法は、 RecyclerListAdapterにリスナーを実装させることです。







 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; }
      
      





アダプターが変更を認識できるように、 notifyItemRemoved()



およびnotifyItemMoved()



メソッドを呼び出すことが非常に重要です。 また、 view



コンポーネントが新しいインデックスに移動するたびに要素の位置を変更することに注意してください。 移動の最後(「ドロップ」イベント)ではありません







onMove()



およびonSwiped()



メソッドをオーバーライドする必要があるため、 SimpleItemTouchHelperCallback



作成に戻ることができます。 まず、アダプターのコンストラクターとフィールドを追加します。







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





次に、残りのイベントを再定義し、これをアダプターに報告します。







 @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()); }
      
      





その結果、 Callback



クラスは次のようになります。







 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()); } }
      
      





コールバックの準備ができたら、 ItemTouchHelper



を作成してattachToRecyclerView(RecyclerView)



メソッドを呼び出すことができます(たとえば、 MainFragment.javaで )。







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





開始後、次のようなものが表示されます。







結果







おわりに



これは、 ItemTouchHelper



最も単純化された実装です。 ただし、サードパーティのライブラリを使用して、 RecyclerView



標準のドラッグアンドドロップおよびスワイプしてRecyclerView



アクションを実装する必要がないことに気付くかもしれません。 次の部分では、ドラッグアンドドロップ時の要素の外観にさらに注意を払います。







ソースコード



GitHubでプロジェクトを作成し、このシリーズの記事で取り上げられていることを実証しました: Android-ItemTouchHelper-Demo最初のコミットは主にこの部分と2番目に少し関連します。







→RecyclerViewでドラッグしてスワイプします。 パート2:コントローラー、グリッド、およびカスタムアニメーションのドラッグアンドドロップ








All Articles