
在上一篇文章的基础上 ,我将继续讨论ItemDecoration
和ItemAnimator
并尝试使用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。 第一部分