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

请求提供Android OverScroller类的最小可运行示例

使用OverScroller实现Android平滑滚动的最小示例

核心逻辑

OverScroller负责处理滚动的物理计算,配合computeScroll()方法驱动滚动动画,通过触摸事件触发滚动请求,最终在onDraw()中更新视图位置实现平滑效果。

完整自定义View代码

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.widget.OverScroller

class OverScrollerDemoView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    private val scroller = OverScroller(context)
    private val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        color = Color.BLUE
        style = Paint.Style.FILL
    }
    // 可滚动方块的位置与尺寸
    private var squareX = 0f
    private var squareY = 200f
    private val squareSize = 200f

    // 触摸起始点记录
    private var lastTouchX = 0f
    private var lastTouchY = 0f

    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                // 终止当前未完成的滚动动画
                if (!scroller.isFinished) {
                    scroller.abortAnimation()
                }
                lastTouchX = event.x
                lastTouchY = event.y
                return true
            }
            MotionEvent.ACTION_MOVE -> {
                // 计算触摸偏移量
                val dx = lastTouchX - event.x
                val dy = lastTouchY - event.y
                // 启动平滑滚动:起始坐标、偏移量、滚动时长(500ms)
                scroller.startScroll(
                    squareX.toInt(), squareY.toInt(),
                    dx.toInt(), dy.toInt(),
                    500
                )
                lastTouchX = event.x
                lastTouchY = event.y
                // 触发重绘,驱动computeScroll执行
                invalidate()
            }
        }
        return super.onTouchEvent(event)
    }

    override fun computeScroll() {
        // 判断滚动是否处于进行中
        if (scroller.computeScrollOffset()) {
            // 更新方块的当前位置
            squareX = scroller.currX.toFloat()
            squareY = scroller.currY.toFloat()
            // 再次触发重绘,直到滚动完成
            invalidate()
        }
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        // 绘制可滚动的蓝色方块
        canvas.drawRect(squareX, squareY, squareX + squareSize, squareY + squareSize, paint)
    }
}

关键代码说明

  • OverScroller初始化:传入上下文实例,自动适配系统滚动的物理特性(如减速、回弹)。
  • 触摸事件处理:
    • ACTION_DOWN:停止当前动画并记录触摸起点,避免滚动冲突。
    • ACTION_MOVE:计算触摸偏移后调用startScroll()启动平滑滚动,同时触发重绘。
  • computeScroll():滚动动画的核心驱动方法,每次重绘都会触发。通过computeScrollOffset()判断滚动状态,更新视图位置后再次触发重绘,直到滚动结束。
  • 绘制逻辑:在onDraw()中根据实时更新的坐标绘制方块,呈现平滑滚动的视觉效果。

使用方式

在布局文件中直接引用该自定义View:

<com.yourpackage.OverScrollerDemoView
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

替换com.yourpackage为你的项目包名,运行后触摸拖动屏幕即可看到蓝色方块的平滑滚动效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 20:32:13