Tips for professional use RecyclerView. Part 2

Original author: Arif Khan
  • Transfer

Tips for professional use RecyclerView.  Part 2


Continuing the previous article in this I will tell you about ItemDecorationand ItemAnimatorand try to explain how it works in RecyclerViewthe example of a simple application that is available on Github .


1. ItemDecoration


ItemDecorationused to decorate list items in RecyclerView.


With the help ItemDecorationyou can add separators between view-components, align them or split them in equal intervals. To add a simple separator between view-components, use the class DividerItemDecorationthat can be found in the support library version 25.1.0 and higher. The following code snippet demonstrates its implementation:


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

The best way to create your own separator is to extend the class RecyclerView.ItemDecoration. In the sample application, I used GridLayoutManagerand applied CharacterItemDecorationto RecyclerView:


recyclerView.addItemDecoration(new CharacterItemDecoration(50));

Here it CharacterItemDecorationsets the offset ( English offset) to 50 pixels in its constructor and overrides getItemOffsets(...). Inside the method, getItemOffsets()each field outRectsdetermines the number of pixels that must be set for each viewcomponent, like internal and external indents. Since I used GridLayoutManagerand wanted to set equal distances between the grid elements, I set the right padding to 25 pixels (i.e. offset / 2) for each even element and the left padding to 25 pixels for each odd element, while keeping the top padding the same for all items.


Indents of elements in the grid


2. ItemAnimator


ItemAnimatorUsed to animate elements or viewcomponents inside RecyclerView.


Animating items in the list


Let's make our app Instagram-like by expanding DefaultItemAnimatorand redefining several methods.


publicbooleancanReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder){
        returntrue;
}

The method canReuseUpdatedViewHolder(...)determines whether the same will ViewHolderbe used for animation if the data of this element changes. If it returns false, then both ViewHoldersold and updated are passed to the method 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) {
                returnnew CharacterItemHolderInfo((String) payload);
            }
        }
    }
    returnsuper.recordPreLayoutInformation(state, viewHolder, changeFlags, payloads);
}
publicstaticclassCharacterItemHolderInfoextendsItemHolderInfo{
        public String updateAction;
        publicCharacterItemHolderInfo(String updateAction){
            this.updateAction = updateAction;
        }
}

RecyclerViewcalls the method recordPreLayoutInformation(...)before drawing starts layout. ItemAnimatormust write down the necessary information about the viewcomponent before it is overwritten, moved or deleted. The data returned by this method will be transferred to the corresponding animation method (in our case it is animateChange(...)).


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

RecyclerViewcalls a method animateChange(...)when the adapter element is present at the same time before and after drawing after calling the method notifyItemChanged(int). This method can also be used when calling notifyDataSetChanged(), if the adapter uses stable identifiers. This is necessary in order to RecyclerViewbe able to reuse the viewcomponents in the same ViewHolders. Note that this method takes as arguments: (ViewHolder oldHolder, ViewHolder newHolder, ItemHolderInfo preInfo, ItemHolderInfo postInfo) . As we reuse ViewHolder, both oldHolder and newHolder are the same.


Whenever a user double-clicks on any item, the following method is called:


notifyItemChanged(position, ACTION_LIKE_IMAGE_DOUBLE_CLICKED);

This starts the whole call chain: canReuseUpdatedViewHolder(...), recordPreLayoutInformation(...)and, ultimately, animateChange(...)in ItemAnimatorwhich, in turn, animates a member list and a heart icon in the element (for example SFII above).


This is the second part of a series of articles about RecyclerView. If you missed the first part, then read it here .


A few more good articles on the topic RecyclerView:



← Tips for professional use RecyclerView. Part 1


Also popular now: