如何实现RecyclerView列表项滑动切换时的选中缩放效果
你之前用LinearLayout动态修改边距的方案会触发全布局重测重排,不仅性能差还容易出现视觉卡顿跳跃,推荐以下三种适配不同场景的实现方案:
方案1:ViewPager2实现(适配滑动切换+选中突出的场景)
ViewPager2自带滑动状态监听和页面变换回调,无需手动计算滑动距离调整布局,性能更流畅:
- 首先设置
offscreenPageLimit为你需要同时展示的可见卡片数量,避免左右侧卡片加载闪烁 - 给ViewPager2设置自定义
PageTransformer,根据页面偏移量动态调整缩放比例和透明度,核心代码如下:
viewPager2.setPageTransformer { page, position -> when { position < -1 -> { // 超出左侧屏幕外 page.scaleX = 0.8f page.scaleY = 0.8f page.alpha = 0.8f } position <= 1 -> { // 可视区域内的页面 val offset = Math.abs(position) val scale = 1 - 0.2f * offset page.scaleX = scale page.scaleY = scale page.alpha = 0.8f + 0.2f * (1 - offset) } else -> { // 超出右侧屏幕外 page.scaleX = 0.8f page.scaleY = 0.8f page.alpha = 0.8f } } }
- 卡片间距可通过
MarginPageTransformer设置,也可直接在卡片布局根节点加左右内边距实现。
方案2:RecyclerView实现(适配选项数量多、需自定义交互的场景)
如果你的选项数量较多,或者需要更灵活的交互逻辑,可选择横向RecyclerView实现:
- 给RecyclerView添加滚动监听,计算可见区域内距离中心最近的item作为选中项
- 在Adapter的
onBindViewHolder中根据item与控件中心的距离动态调整item的缩放、透明度 - 配合
LinearSnapHelper实现松手后自动将最近的item滚动到居中位置,模拟选中效果。
方案3:属性动画实现(适配固定数量、仅点击切换的场景)
如果你的选项是固定数量无需滑动,仅点击切换选中状态,直接用属性动画实现缩放效果即可:
// 选中状态动画 val selectAnim = AnimatorSet() selectAnim.playTogether( ObjectAnimator.ofFloat(selectedTab, "scaleX", 0.8f, 1f), ObjectAnimator.ofFloat(selectedTab, "scaleY", 0.8f, 1f) ) selectAnim.duration = 200 selectAnim.start() // 取消选中状态动画 val unselectAnim = AnimatorSet() unselectAnim.playTogether( ObjectAnimator.ofFloat(unselectedTab, "scaleX", 1f, 0.8f), ObjectAnimator.ofFloat(unselectedTab, "scaleY", 1f, 0.8f) ) unselectAnim.duration = 200 unselectAnim.start()
以上方案都是基于视图绘制层面做变换,不会触发布局重测,流畅度远高于动态修改布局参数的实现。
内容的提问来源于stack exchange,提问作者Siddhesh Pawar
相关产品推荐
相关产品推荐

