RecyclerViewをプロが使用するためのヒント。 パート2

RecyclerViewをプロが使用するためのヒント。パート2







前の記事を続けて、この記事ではItemDecoration



ItemAnimator



について説明し、 Githubで利用可能な単純なアプリケーションの例を使用して、 RecyclerView



でのそれらの動作の原理を説明します。







1. ItemDecoration



ItemDecoration



RecyclerView



リストアイテムを装飾するために使用されます。







ItemDecoration



を使用すると、 view



コンポーネント間に仕切りを追加したり、配置したり、等間隔で分割したりできます。 view



コンポーネント間に単純なセパレーターを追加するには、サポートライブラリバージョン25.1.0以降にあるDividerItemDecoration



クラスを使用します。 次のコードフラグメントは、その実装を示しています。







 mDividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), mLayoutManager.getOrientation()); recyclerView.addItemDecoration(mDividerItemDecoration);
      
      





独自のセパレータを作成する最良の方法は、 RecyclerView.ItemDecoration



クラスを拡張することです。 サンプルアプリケーションでは、 GridLayoutManager



を使用し、 CharacterItemDecoration



RecyclerView



適用しました。







 recyclerView.addItemDecoration(new CharacterItemDecoration(50));
      
      





ここで、 CharacterItemDecoration



は、コンストラクターでオフセット( getItemOffsets(...)



)を50ピクセルに設定し、 getItemOffsets(...)



をオーバーライドします。 getItemOffsets()



メソッド内で、各outRects



フィールドは、内部および外部マージンと同様に、各view



コンポーネントに設定する必要があるピクセル数を決定します。 GridLayoutManager



を使用し、グリッド要素間の等距離を設定するため、各偶数要素に対して右側のインデントを25ピクセル(つまり、オフセット/ 2)に設定し、奇数要素ごとに左側のインデントを25ピクセルに設定します。すべての要素に対して。







グリッドのインデント







2. ItemAnimator



ItemAnimator



RecyclerView



内の要素のアニメーション化またはコンポーネントのview



使用されます。







リストアイテムのアニメーション化







DefaultItemAnimator



を拡張し、いくつかのメソッドをオーバーライドすることにより、アプリケーションを「Instagramライク」にしましょう。







 public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) { return true; }
      
      





canReuseUpdatedViewHolder(...)



メソッドは、この要素のデータが変更された場合に同じViewHolder



をアニメーションに使用するかどうかを決定します。 false



返す場合、 ViewHolders



(古いものと更新されたもの)の両方がanimateChange(...)



メソッドに渡されます。







 public ItemHolderInfo recordPreLayoutInformation(@NonNull RecyclerView.State state, @NonNull RecyclerView.ViewHolder viewHolder, int changeFlags, @NonNull List<Object> payloads) { if (changeFlags == FLAG_CHANGED) { for (Object payload : payloads) { if (payload instanceof String) { return new CharacterItemHolderInfo((String) payload); } } } return super.recordPreLayoutInformation(state, viewHolder, changeFlags, payloads); } public static class CharacterItemHolderInfo extends ItemHolderInfo { public String updateAction; public CharacterItemHolderInfo(String updateAction) { this.updateAction = updateAction; } }
      
      





RecyclerView



は、 layout



レンダリングが開始される前にrecordPreLayoutInformation(...)



メソッドを呼び出します。 ItemAnimator



は、上書き、移動、または削除する前に、 view



コンポーネントに関する必要な情報を記録する必要があります。 このメソッドによって返されるデータは、対応するアニメーションメソッドに転送されます(この場合、これはanimateChange(...)



)。







 @Override public boolean animateChange(@NonNull RecyclerView.ViewHolder oldHolder, @NonNull RecyclerView.ViewHolder newHolder, @NonNull ItemHolderInfo preInfo, @NonNull ItemHolderInfo postInfo) { if (preInfo instanceof CharacterItemHolderInfo) { CharacterItemHolderInfo recipesItemHolderInfo = (CharacterItemHolderInfo) preInfo; CharacterRVAdapter.CharacterViewHolder holder = (CharacterRVAdapter.CharacterViewHolder) newHolder; if (CharacterRVAdapter.ACTION_LIKE_IMAGE_DOUBLE_CLICKED.equals(recipesItemHolderInfo.updateAction)) { animatePhotoLike(holder); } } return false; } private void animatePhotoLike(final CharacterRVAdapter.CharacterViewHolder holder) { holder.likeIV.setVisibility(View.VISIBLE); holder.likeIV.setScaleY(0.0f); holder.likeIV.setScaleX(0.0f); AnimatorSet animatorSet = new AnimatorSet(); ObjectAnimator scaleLikeIcon = ObjectAnimator.ofPropertyValuesHolder (holder.likeIV, PropertyValuesHolder.ofFloat("scaleX", 0.0f, 2.0f), PropertyValuesHolder.ofFloat("scaleY", 0.0f, 2.0f), PropertyValuesHolder.ofFloat("alpha", 0.0f, 1.0f, 0.0f)); scaleLikeIcon.setInterpolator(DECELERATE_INTERPOLATOR); scaleLikeIcon.setDuration(1000); ObjectAnimator scaleLikeBackground = ObjectAnimator.ofPropertyValuesHolder (holder.characterCV, PropertyValuesHolder.ofFloat("scaleX", 1.0f, 0.95f, 1.0f), PropertyValuesHolder.ofFloat("scaleY", 1.0f, 0.95f, 1.0f)); scaleLikeBackground.setInterpolator(DECELERATE_INTERPOLATOR); scaleLikeBackground.setDuration(600); animatorSet.playTogether(scaleLikeIcon, scaleLikeBackground); animatorSet.start(); }
      
      





notifyItemChanged(int)



メソッドを呼び出した後、レンダリングの前後にアダプター要素が存在する場合、 RecyclerView



animateChange(...)



メソッドを呼び出します。 このメソッドは、アダプターが安定した識別子を使用する場合にnotifyDataSetChanged()



呼び出すときにも使用できます。 これは、 RecyclerView



が同じViewHolders



view



コンポーネントを再利用できるようにするために必要ViewHolders



。 このメソッドは引数として受け取ることに注意してください(ViewHolder oldHolder、ViewHolder newHolder、ItemHolderInfo preInfo、ItemHolderInfo postInfo)ViewHolder



を再利用しているViewHolder



、oldHolderとnewHolderは同じです。







ユーザーがアイテムをダブルクリックするたびに、次のメソッドが呼び出されます。







 notifyItemChanged(position, ACTION_LIKE_IMAGE_DOUBLE_CLICKED);
      
      





これにより、コールチェーン全体が開始されますcanReuseUpdatedViewHolder(...)



recordPreLayoutInformation(...)



、そして最終的にItemAnimator



animateChange(...)



は、リスト要素とその要素のハートアイコンをアニメーション化しますanimateChange(...)



上記のgifの例)。







これは、 RecyclerView



に関する一連の記事の第2部です。 最初の部分を見逃した場合は、 ここで読んでください







RecyclerView



に関するさらに良い記事:









←プロユースのRecyclerViewのヒント。 パート1








All Articles