Android OverScroller详解

主要总结一下使用手势相关的代码逻辑。主要是单点拖动,多点拖动,fling和OveScroll的实现。每个手势都会有代码片段。

为了节约你的时间,我特地将文章大致内容总结如下:

手势Drag的实现和原理
手势Fling的实现和原理
OverScroll效果和EdgeEffect效果的实现和原理。

Drag
Drag是最为基本的手势:用户可以使用手指在屏幕上滑动,以拖动屏幕相应内容移动。实现Drag手势其实很简单,步骤如下:

在ACTION_DOWN事件发生时,调用getX和getY函数获得事件发生的x,y坐标值,并记录在mLastX和mLastY变量中。
在ACTION_MOVE事件发生时,调用getX和getY函数获得事件发生的x,y坐标值,将其与mLastX和mLastY比较,如果二者差值大于一定限制(ScaledTouchSlop),就执行scrollBy函数,进行滚动,最后更新mLastX和mLastY的值。
在ACTION_UP和ACTION_CANCEL事件发生时,清空mLastX,mLastY。

@Override
public boolean onTouchEvent(MotionEvent event) {
    int actionId = MotionEventCompat.getActionMasked(event);
    switch (actionId) {
        case MotionEvent.ACTION_DOWN:
            mLastX = event.getX();
            mLastY = event.getY();
            mIsBeingDragged = true;
            if (getParent() != null) {
                getParent().requestDisallowInterceptTouchEvent(true);
            }
            break;
        case MotionEvent.ACTION_MOVE:
            float curX = event.getX();
            float curY = event.getY();
            int deltaX = (int) (mLastX - curX);
            int deltaY = (int) (mLastY - curY);
            if (!mIsBeingDragged && (Math.abs(deltaX)> mTouchSlop ||
                                                    Math.abs(deltaY)> mTouchSlop)) {
                mIsBeingDragged = true;
                // 让第一次滑动的距离和之后的距离不至于差距太大
                // 因为第一次必须>TouchSlop,之后则是直接滑动
                if (deltaX > 0) {
                    deltaX -= mTouchSlop;
                } else {
                    deltaX += mTouchSlop;
                }
                if (deltaY > 0) {
                    deltaY -= mTouchSlop;
                } else {
                    deltaY += mTouchSlop;
                }
            }
            // 当mIsBeingDragged为true时,就不用判断> touchSlopg啦,不然会导致滚动是一段一段的
            // 不是很连续
            if (mIsBeingDragged) {
                    scrollBy(deltaX, deltaY);
                    mLastX = curX;
                    mLastY = curY;
            }
            break;
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
            mIsBeingDragged = false;
            mLastY = 0;
            mLastX = 0;
            break;
        default:
    }
    return mIsBeingDragged;
}

多触点Drag
上边的代码只适用于单点触控的手势,如果你是两个手指触摸屏幕,那么它只会根据你第一个手指滑动的情况来进行屏幕滚动。更为致命的是,当你先松开第一个手指时,由于我们少监听了ACTION_POINTER_UP事件,将会导致屏幕突然滚动一大段距离,因为第二个手指移动事件的x,y值会和第一个手指移动时留下的mLastX和mLastY比较,导致屏幕滚动。

如果我们要监听并处理多触点的事件,我们还需要对ACTION_POINTER_DOWN和ACTION_POINTER_UP事件进行监听,并且在ACTION_MOVE事件时,要记录所有触摸点事件发生的x,y值。

当ACTION_POINTER_DOWN事件发生时,我们要记录第二触摸点事件发生的x,y值为mSecondaryLastX和mSecondaryLastY,和第二触摸点pointer的id为mSecondaryPointerId

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安卓兼职framework应用工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值