如何实现RecyclerView选中项展开效果?横向滚动布局技术求助
嘿,这个需求很常见,核心就是结合RecyclerView的选中回调和属性动画来实现平滑的尺寸展开效果,我给你整理了适配你现有Adapter结构的具体实现步骤:
实现步骤
1. 先定义尺寸资源
在res/values/dimens.xml里配置默认尺寸和选中后的目标尺寸,方便统一修改:
<dimen name="nav_item_default_width">60dp</dimen> <dimen name="nav_item_selected_width">120dp</dimen> <dimen name="nav_item_default_height">60dp</dimen> <!-- 如果高度需要变化,再添加选中状态的高度 -->
2. 改造ViewHolder保存状态
在你的FilterItemHolder里添加选中状态标记、动画引用,同时初始化默认尺寸:
public class FilterItemHolder extends RecyclerView.ViewHolder { final View rootView; boolean isItemSelected = false; ValueAnimator runningAnimator; public FilterItemHolder(View itemView) { super(itemView); this.rootView = itemView; // 初始化默认尺寸 resetToDefaultSize(); } // 封装恢复默认尺寸的方法 private void resetToDefaultSize() { Context context = rootView.getContext(); ViewGroup.LayoutParams params = rootView.getLayoutParams(); params.width = (int) context.getResources().getDimension(R.dimen.nav_item_default_width); params.height = (int) context.getResources().getDimension(R.dimen.nav_item_default_height); rootView.setLayoutParams(params); } }
3. 利用OnItemSelectedListener处理选中动画
你已经实现了OnItemSelectedListener,直接在回调里触发展开动画:
@Override public void onItemSelected(RecyclerView parent, View view, int position, long id) { FilterItemHolder holder = (FilterItemHolder) parent.findViewHolderForAdapterPosition(position); if (holder == null) return; // 先取消正在运行的动画,避免冲突 if (holder.runningAnimator != null && holder.runningAnimator.isRunning()) { holder.runningAnimator.cancel(); } Context context = view.getContext(); int targetWidth = (int) context.getResources().getDimension(R.dimen.nav_item_selected_width); int currentWidth = holder.rootView.getWidth(); // 创建宽度变化的属性动画 holder.runningAnimator = ValueAnimator.ofInt(currentWidth, targetWidth); holder.runningAnimator.addUpdateListener(animation -> { int animatedWidth = (int) animation.getAnimatedValue(); ViewGroup.LayoutParams params = holder.rootView.getLayoutParams(); params.width = animatedWidth; // 如果需要同步修改高度,在这里设置params.height holder.rootView.setLayoutParams(params); }); holder.runningAnimator.setDuration(300); // 动画时长可根据需求调整 holder.runningAnimator.start(); holder.isItemSelected = true; }
4. 处理未选中项的恢复动画
在onItemNotSelected回调里,把之前选中的项恢复到默认尺寸:
@Override public void onItemNotSelected(RecyclerView parent, View view, int position, long id) { FilterItemHolder holder = (FilterItemHolder) parent.findViewHolderForAdapterPosition(position); if (holder == null || !holder.isItemSelected) return; if (holder.runningAnimator != null && holder.runningAnimator.isRunning()) { holder.runningAnimator.cancel(); } Context context = view.getContext(); int targetWidth = (int) context.getResources().getDimension(R.dimen.nav_item_default_width); int currentWidth = holder.rootView.getWidth(); holder.runningAnimator = ValueAnimator.ofInt(currentWidth, targetWidth); holder.runningAnimator.addUpdateListener(animation -> { int animatedWidth = (int) animation.getAnimatedValue(); ViewGroup.LayoutParams params = holder.rootView.getLayoutParams(); params.width = animatedWidth; holder.rootView.setLayoutParams(params); }); holder.runningAnimator.setDuration(300); holder.runningAnimator.start(); holder.isItemSelected = false; }
5. 优化ViewHolder回收时的状态
避免内存泄漏和状态混乱,在ViewHolder被回收时清理动画并恢复默认状态:
@Override public void onViewRecycled(@NonNull FilterItemHolder holder) { super.onViewRecycled(holder); if (holder.runningAnimator != null) { holder.runningAnimator.cancel(); holder.runningAnimator = null; } holder.isItemSelected = false; holder.resetToDefaultSize(); }
额外提示
- 给子项里的ImageView设置合适的
scaleType(比如centerInside或fitCenter),避免尺寸变化时图片拉伸变形。 - 如果需要更细腻的动画效果,可以同时给ImageView添加alpha缩放动画,配合尺寸变化。
内容的提问来源于stack exchange,提问作者asmhan
相关产品推荐
相关产品推荐

