📜 ⬆️ ⬇️

Tips for professional use RecyclerView. Part 2

Tips for professional use RecyclerView. Part 2


Continuing the previous article , in this one I’ll talk about ItemDecoration and ItemAnimator and try to explain how they work in RecyclerView using the example of a simple application that is available on Github .


1. ItemDecoration


ItemDecoration used to decorate list items in a RecyclerView .


With the help of ItemDecoration you can add dividers between view components, align them, or split them in equal intervals. To add a simple separator between view components, use the DividerItemDecoration class, which 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 RecyclerView.ItemDecoration class. In the sample application, I used the GridLayoutManager and applied CharacterItemDecoration to the RecyclerView :


 recyclerView.addItemDecoration(new CharacterItemDecoration(50)); 

Here CharacterItemDecoration sets the offset ( born offset) to 50 pixels in its constructor and overrides getItemOffsets(...) . Inside the getItemOffsets() method, each outRects field determines the number of pixels that must be set for each view component, like internal and external indents. Since I used GridLayoutManager and wanted to set equal distances between 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


ItemAnimator used to animate items or view components within RecyclerView .


Animating items in the list


Let's make our application Instagram-like by extending DefaultItemAnimator and redefining several methods.


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

The canReuseUpdatedViewHolder(...) method determines whether the same ViewHolder be used for animation if the data of this element changes. If it returns false , then both ViewHolders — old and updated — are passed to the animateChange(...) method.


 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 calls the recordPreLayoutInformation(...) method before drawing a layout . ItemAnimator must record the necessary information about the view component before it is overwritten, moved or deleted. The data returned by this method will be transferred to the corresponding animation method (in our case, this is 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 calls the animateChange(...) method when the adapter element is present both before and after drawing after calling the notifyItemChanged(int) method. This method can also be used when calling notifyDataSetChanged() , if the adapter uses stable identifiers. This is necessary so that RecyclerView can reuse view components in the same ViewHolders . Note that this method takes as arguments: (ViewHolder oldHolder, ViewHolder newHolder, ItemHolderInfo preInfo, ItemHolderInfo postInfo) . Because we reuse the ViewHolder , both oldHolder and newHolder are the same.


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


 notifyItemChanged(position, ACTION_LIKE_IMAGE_DOUBLE_CLICKED); 

This runs the entire call chain: canReuseUpdatedViewHolder(...) , recordPreLayoutInformation(...) and, ultimately, animateChange(...) in ItemAnimator , which in turn animates the list item and the heart icon in this element ( example on the gifs 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 RecyclerView :



← Tips for professional use RecyclerView. Part 1


')

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


All Articles