Conseils pour une utilisation professionnelle de RecyclerView. 2e partie

Conseils pour une utilisation professionnelle de RecyclerView. 2e partie


Poursuivant l' article précédent , je vais parler ici de ItemDecoration et ItemAnimator et essayer d'expliquer le principe de leur travail dans RecyclerView utilisant un exemple d'une application simple qui est disponible sur Github .


1. ArticleDécoration


ItemDecoration utilisé pour décorer des éléments de liste dans un RecyclerView .


Avec ItemDecoration vous pouvez ajouter des séparateurs entre les composants de view , les aligner ou les diviser à intervalles égaux. Pour ajouter un simple séparateur entre les composants de view , utilisez la classe DividerItemDecoration , qui se trouve dans la bibliothèque de support version 25.1.0 et supérieure. Le fragment de code suivant illustre son implémentation:


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

La meilleure façon de créer votre propre séparateur est d'étendre la classe RecyclerView.ItemDecoration . Dans l'exemple d'application, j'ai utilisé GridLayoutManager et appliqué CharacterItemDecoration à RecyclerView :


 recyclerView.addItemDecoration(new CharacterItemDecoration(50)); 

Ici, CharacterItemDecoration définit l'offset ( eng. Offset) à 50 pixels dans son constructeur et remplace getItemOffsets(...) . À l'intérieur de la méthode getItemOffsets() , chaque champ outRects détermine le nombre de pixels qui doivent être définis pour chaque composant de view , comme pour l'indentation et l'indentation. Puisque j'ai utilisé le GridLayoutManager et que GridLayoutManager voulais définir des distances égales entre les éléments de la grille, j'ai défini le retrait à droite sur 25 pixels (c'est-à-dire offset / 2) pour chaque élément pair et le retrait à gauche sur 25 pixels pour chaque élément impair, tout en gardant le retrait supérieur identique. pour tous les éléments.


Indentation de la grille


2. ItemAnimator


ItemAnimator utilisé pour animer des éléments ou view composants à l'intérieur d'un RecyclerView .


Animer des éléments dans une liste


Rendons notre application semblable à Instagram en étendant DefaultItemAnimator et en DefaultItemAnimator plusieurs méthodes.


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

La canReuseUpdatedViewHolder(...) détermine si le même ViewHolder utilisé pour l'animation si les données de cet élément changent. S'il renvoie false , les deux ViewHolders - anciens et mis à jour - sont passés à la 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 appelle la recordPreLayoutInformation(...) pour commencer le rendu de la layout . ItemAnimator doit enregistrer les informations nécessaires sur le composant d' view avant qu'il ne soit remplacé, déplacé ou supprimé. Les données retournées par cette méthode seront transférées vers la méthode d'animation correspondante (dans notre cas, c'est 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(); } 

RecyclerView appelle la animateChange(...) lorsque l'élément adaptateur est présent avant et après le rendu après avoir appelé la notifyItemChanged(int) . Cette méthode peut également être utilisée lors de l'appel de notifyDataSetChanged() , si l'adaptateur utilise des identificateurs stables. Cela est nécessaire pour que RecyclerView puisse réutiliser les composants de view dans les mêmes ViewHolders . Notez que cette méthode prend comme arguments: (ViewHolder oldHolder, ViewHolder newHolder, ItemHolderInfo preInfo, ItemHolderInfo postInfo) . Puisque nous réutilisons ViewHolder , oldHolder et newHolder sont identiques.


Chaque fois que l'utilisateur double-clique sur un élément, la méthode suivante est appelée:


 notifyItemChanged(position, ACTION_LIKE_IMAGE_DOUBLE_CLICKED); 

Cela démarre toute la chaîne d'appels: canReuseUpdatedViewHolder(...) , recordPreLayoutInformation(...) et, finalement, animateChange(...) dans ItemAnimator , qui, à son tour, anime l'élément de liste et l'icône du cœur dans cet élément ( exemple dans le GIF ci-dessus).


Ceci est la deuxième partie d'une série d'articles sur RecyclerView . Si vous avez manqué la première partie, lisez-la ici .


Quelques autres bons articles sur RecyclerView :



← Conseils pour une utilisation professionnelle RecyclerView. Partie 1

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


All Articles