OverScroller基础使用

/ 0评 / 0

最近偶然间看到一篇博客Android Scroller 滑动机制介绍了Android中ScrollView的滚动本质,并从源码级别进行了介绍,只能说大佬牛逼了,然后写一个demo来加强记忆咯

1、Scroll的方向傻傻乎乎分不清楚

如图所示,如果需要向右边滚动,参数得为负数scrollBy(-dx.toInt(), -dy.toInt())

file

2、系统给了很多值基础值,需要好好使用

ViewConfiguration viewConfiguration = ViewConfiguration.get(getContext());
//表示滑动的时候,手的移动要大于这个距离才开始移动控件
scaledTouchSlop = viewConfiguration.getScaledTouchSlop();
//获得允许执行一个fling手势动作的最大速度值
scaledMaximumFlingVelocity = viewConfiguration.getScaledMaximumFlingVelocity();
//获得允许执行一个fling手势动作的最小速度值
scaledMinimumFlingVelocity = viewConfiguration.getScaledMinimumFlingVelocity();

3、OverScroller的使用
OverScroller与Scroller大部分api都一模一样,唯一多的就是可以越界滚动一部分长度,这个可以用来做回弹效果

4、简单化的拖动,不如试用下ViewDragHelper

ViewDragHelper

5、滚动的本质

本质上是改变了View.mScrollX和View.mScrollY这两个变量,只会改变控件绘制的位置,控件本身没变

6、其他一些变量
其实View还有mLeft,mTop等等变量,修改这些变量则会移动View在父布局中的位置

View.setLeft/Top/Right/Bottom
View.layout(l,t,r,b);
View.setTranslationX/Y
View.soffsetTopAndBottom

Demo地址

class ScrollTextView : androidx.appcompat.widget.AppCompatButton {

    private val scroll = OverScroller(context)

    private var velocityTracker: VelocityTracker? = null

    private var mLastX: Float = 0f
    private var mLastY: Float = 0f

    private var maxFling: Int = 0
    private var minFling: Int = 0;

    constructor(context: Context) : this(context, null)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        val viewConfiguration = ViewConfiguration.get(getContext())
        maxFling = viewConfiguration.scaledMaximumFlingVelocity
        minFling = viewConfiguration.scaledMinimumFlingVelocity

        Log.i(TAG, "maxFling = $maxFling minFling = $minFling")
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (velocityTracker == null) {
            velocityTracker = VelocityTracker.obtain()
        }
        velocityTracker?.addMovement(event)

        val x = event.rawX
        val y = event.rawY
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                if (!scroll.isFinished) {
                    scroll.abortAnimation()
                }
            }
            MotionEvent.ACTION_MOVE -> {
                val dx = x - mLastX
                val dy = y - mLastY
                scrollBy(-dx.toInt(), -dy.toInt())
            }
            MotionEvent.ACTION_UP,
            MotionEvent.ACTION_CANCEL -> {
                velocityTracker?.let {
                    it.computeCurrentVelocity(1000, maxFling.toFloat())
                    val padding = 30
                    scroll.fling(scrollX, scrollY, -it.xVelocity.toInt(), -it.yVelocity.toInt(), -measuredWidth / 2 + padding, measuredWidth / 2 - padding, -measuredHeight / 2 + padding, measuredHeight / 2 - padding, 20, 20)
                    postInvalidateOnAnimation()
                }
                velocityTracker?.recycle()
                velocityTracker = null
            }
        }
        mLastX = x
        mLastY = y
        return true
    }

    fun startScroll() {
        if (!scroll.isFinished) {
            scroll.abortAnimation()
        }
        scroll.startScroll(scrollX, scrollY, -100, -100, 1000 * 3)
        postInvalidateOnAnimation()
    }

    override fun computeScroll() {
        super.computeScroll()
        if (scroll.computeScrollOffset()) {
            scrollTo(scroll.currX, scroll.currY)
            postInvalidateOnAnimation()
        }
    }
}

ps:一些好用的属性

getCurrVelocity()可以获取剩余的速度
getFinalY/getFinalX 获取滚动的终点

发表回复

您的电子邮箱地址不会被公开。