You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现RecyclerView Item触摸放大、释放缩小效果?

实现垂直RecyclerView Item触摸缩放效果(类似Facebook反应动效)

嘿,这个需求我之前也帮朋友搞过,类似Facebook那种轻触Item放大、松手就还原的动效其实没那么复杂,咱们一步步拆解来实现~

先聊核心逻辑

本质就是靠触摸事件监听+属性动画组合实现:

  • 用户按下Item时,触发一个小幅度的放大动画(比如1.05倍,你可以自己调)
  • 手指抬起或者触摸离开Item时,触发还原动画回到原尺寸
  • 还要注意别和RecyclerView本身的滑动冲突,得让两者都正常工作

具体实现步骤

1. 写个全局的触摸监听类

我习惯写一个ItemScaleTouchListener实现RecyclerView.OnItemTouchListener,这样不用在Adapter里重复写代码,全局生效:

class ItemScaleTouchListener(private val recyclerView: RecyclerView) : RecyclerView.OnItemTouchListener {
    private var currentTouchedView: View? = null
    // 缩放参数,按需调整
    private val SCALE_UP = 1.05f
    private val SCALE_NORMAL = 1.0f

    override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
        when (e.action) {
            MotionEvent.ACTION_DOWN -> {
                // 找到当前触摸的那个Item View
                currentTouchedView = rv.findChildViewUnder(e.x, e.y)
                currentTouchedView?.let { scaleView(it, SCALE_UP) }
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                currentTouchedView?.let {
                    scaleView(it, SCALE_NORMAL)
                    currentTouchedView = null
                }
            }
        }
        // 返回false,让RecyclerView正常处理滑动事件
        return false
    }

    override fun onTouchEvent(rv: RecyclerView, e: MotionEvent) {}
    override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}

    private fun scaleView(view: View, targetScale: Float) {
        // 先取消之前的动画,避免快速触摸导致动画混乱
        view.animate().cancel()
        // 用属性动画做平滑缩放
        ObjectAnimator.ofPropertyValuesHolder(
            view,
            PropertyValuesHolder.ofFloat(View.SCALE_X, targetScale),
            PropertyValuesHolder.ofFloat(View.SCALE_Y, targetScale)
        ).apply {
            duration = 150 // 动画时长,Facebook的动效大概是这个速度
            interpolator = DecelerateInterpolator() // 减速插值器,放大时更自然
            start()
        }
    }
}

2. 给RecyclerView挂上这个监听

在你的Activity或者Fragment里,给RecyclerView添加这个监听就行:

recyclerView.addOnItemTouchListener(ItemScaleTouchListener(recyclerView))

3. 一些细节优化

  • 如果你的Item里有按钮、CheckBox这类可点击的子View,得确保它们的触摸事件不受影响。可以在onInterceptTouchEvent里判断触摸的View是不是可点击的,如果是就跳过缩放逻辑;或者调整子View的触摸优先级。
  • 想让动效更像Facebook的话,可以把插值器换成OvershootInterpolator(),放大时会有一点点回弹的感觉,更灵动。
  • 要是你需要给不同Item设置不同的缩放比例,那不如直接在Adapter的onBindViewHolder里给每个Item加触摸监听,比如:
override fun onBindViewHolder(holder: YourViewHolder, position: Int) {
    // 其他绑定逻辑...
    holder.itemView.setOnTouchListener { v, event ->
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                v.animate()
                    .scaleX(1.05f)
                    .scaleY(1.05f)
                    .setDuration(150)
                    .setInterpolator(DecelerateInterpolator())
                    .start()
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                v.animate()
                    .scaleX(1.0f)
                    .scaleY(1.0f)
                    .setDuration(150)
                    .setInterpolator(DecelerateInterpolator())
                    .start()
            }
        }
        // 这里返回false,让Item的点击事件能正常触发
        false
    }
}

这种方式更灵活,适合个性化需求多的场景。


内容的提问来源于stack exchange,提问作者Vitor Ferreira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:14:53