专业使用RecyclerView的提示。 第二部分

专业使用RecyclerView的提示。第二部分


上一篇文章的基础上 ,我将继续讨论ItemDecorationItemAnimator并尝试使用Github上提供的一个简单应用程序示例来说明它们在RecyclerView中的工作原理。


1. ItemDecoration


ItemDecoration用于装饰RecyclerView列表项。


使用ItemDecoration您可以在view组件之间添加分隔线,对齐它们或以相等的间隔对其进行拆分。 要在view组件之间添加简单的分隔符,请使用DividerItemDecoration类,该类可以在支持库版本25.1.0及更高版本中找到。 以下代码片段演示了其实现:


 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个像素(即offset / 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调用recordPreLayoutInformation(...)方法开始layout渲染。 ItemAnimator必须在覆盖,移动或删除view组件之前记录有关该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(...) notifyItemChanged(int)方法。 如果适配器使用稳定的标识符,则在调用notifyDataSetChanged()时也可以使用此方法。 这是必需的,以便RecyclerView可以在同一ViewHolders重用view组件。 请注意,此方法采用以下参数作为参数: (ViewHolder oldHolder,ViewHolder newHolder,ItemHolderInfo preInfo,ItemHolderInfo postInfo) 。 由于我们正在重用ViewHolder ,因此oldHolder和newHolder都是相同的。


每当用户双击任何项目时,都会调用以下方法:


 notifyItemChanged(position, ACTION_LIKE_IMAGE_DOUBLE_CLICKED); 

这将启动整个调用链: canReuseUpdatedViewHolder(...)recordPreLayoutInformation(...)以及最终在ItemAnimator animateChange(...) ,从而使该元素中的列表项和心脏图标动画(上面的GIF中的示例)。


这是有关RecyclerView的系列文章的第二部分。 如果您错过了第一部分,请在此处阅读。


RecyclerView上还有一些更好的文章:



←专业使用技巧RecyclerView。 第一部分

Source: https://habr.com/ru/post/zh-CN426773/


All Articles