Android Touch事件总结 二 (双指实现RecyclerView的快速滚动)

来源:互联网 发布:免费pk10分析软件 编辑:程序博客网 时间:2024/05/17 04:14

说明:本博客为原创,转载请注明出处 CSDN-ANDROID笔记栈
由于作者水平有限,错误在所难免,请见谅,可以留言,本人会及时改正


索引

  • MotionEvent
  • Demo


在 Android Touch事件总结 一 中介绍了Android Touch事件的分发,拦截,消费。
本篇是对总结一的补充和实战。

MotionEvent

在分发、拦截、消费方法中传入的参数都是MotionEvent对象,所以有必要对MotionEvent类进行分析,大家可以参考这篇博文:Android MotionEvent详解

我重点强调下MotionEvnet的几个方法在多指触摸事件中的作用:

getActionIndex:在ACTION_POINTER_DOWN和ACTION_POINTER_UP事件中返回索引

getPointerId:通过索引获取id

findPointerIndex:通过id获取索引

pointerId在整个触摸事件[DOWN->UP]中是不变的,但是index可能会变。


Demo

GitHub地址: GitHub
环境: Windows7+JAVA8
IDE: AndroidStdio2.2.2
compileSdkVersion:24
测试设备:Nexus5(6.0.1)

运行结果截图:
多指快递滚动
黑色和黑色线是手指的移动轨迹,30%是整个移动轨迹相对于View整个高度的百分比(向下滑动>0,向上滑动<0)
只有双指滑动在支持快递滚动(RecyclerView中的Touch事件被拦截),单指没有效果(RecyclerView正常滚动)

下面是核心代码:

@Overridepublic boolean dispatchTouchEvent(MotionEvent ev){    switch (ev.getActionMasked())    {        case MotionEvent.ACTION_DOWN:        {            resetFinger(); // 重置手指状态            final int pointerId = ev.getPointerId(ev.getActionIndex()); // 获取当前手指(单手指)的id            final int index = ev.findPointerIndex(pointerId);            mFirstFinger = new Finger(pointerId); // 初始化第一根手指            TouchPoint touchPoint = new TouchPoint(ev.getX(index), ev.getY(index)); // 保存当前的坐标x&y值            // 这边需要说明的是调用ArrayList.add(MotionEvent) 之后整个List中的值都会被最新添加的对象给覆盖!未查明原因,有知道原因的请告知,谢谢。            mFirstFinger.add(touchPoint); // 添加到ArrayList中            mFirstFinger.setTargetPoint(touchPoint);                break;        }        case MotionEvent.ACTION_UP:        case MotionEvent.ACTION_CANCEL:        case MotionEvent.ACTION_OUTSIDE:        {            mFingerTouchMode = false; // 标志位,用于什么时候拦截Touch事件            resetFinger(); // 重置手指            break;        }        case MotionEvent.ACTION_MOVE:        {            if (mFirstFinger != null)            {                final int index = ev.findPointerIndex(mFirstFinger.id);                TouchPoint touchPoint = new TouchPoint(ev.getX(index), ev.getY(index));                mFirstFinger.add(touchPoint); // 添加手指移动轨迹                if (mSecondFinger == null)                {                    mFirstFinger.setTargetPoint(touchPoint);                }            }            if (mSecondFinger != null) // 如果是多指状态,添加第二根手指的移动轨迹            {                final int index = ev.findPointerIndex(mSecondFinger.id);                TouchPoint touchPoint = new TouchPoint(ev.getX(index), ev.getY(index));                mSecondFinger.add(touchPoint);            }            if (mFirstFinger != null && mSecondFinger != null) // 如果是多指状态,则计算移动距离百分比            {                if (Math.abs(mFirstFinger.touchTime - mSecondFinger.touchTime) <= FINGER_TOUCH_DURATION) // 两根手指的触摸时间<500毫秒                {                    int fd = mFirstFinger.getDistanceFromTargetPoint(); // 计算第一根手指的移动距离                    int sd = mSecondFinger.getDistanceFromTargetPoint(); // 计算第二根手指的移动距离                    if (fd * sd > 0) // 两根手指同向                    {                        mFingerTouchMode = true;                        int dDelta = (fd + sd) / 2;                        mPercent = Math.min((int) (dDelta * 100f * mScale / getHeight()), 100); // 计算百分比                       if (mCallback != null)                       {                        mCallback.onFingerScrolling(mPercent);//  触发回调事件                       }                      }                    }                }                break;            }            case MotionEvent.ACTION_POINTER_DOWN: // 多指状态            {                if (mSecondFinger == null) // 初始化第二根手指                {                    final int pointerId = ev.getPointerId(ev.getActionIndex());                    final int index = ev.findPointerIndex(pointerId);                    mSecondFinger = new Finger(pointerId);                    TouchPoint touchPoint = new TouchPoint(ev.getX(index), ev.getY(index));                    mSecondFinger.add(touchPoint);                    mSecondFinger.setTargetPoint(touchPoint);                    if (mCallback != null)                    {                        mCallback.onFingerStart();                    }                }                break;            }            case MotionEvent.ACTION_POINTER_UP:            {                mFingerTouchMode = ev.getPointerCount() > 2; // 判断当前是不是多指状态                final int pointerUpId = ev.getPointerId(ev.getActionIndex()); // 获取当前是哪根手指触发了UP事件                if (mFirstFinger != null && pointerUpId == mFirstFinger.id) // 如果是第一根手指,交换手指顺序                {                    mFirstFinger = mSecondFinger;                    mFirstFinger.resetTargetPoint();                    mSecondFinger = null;                }                else if (mSecondFinger != null && pointerUpId == mSecondFinger.id)                {                    if (mFirstFinger != null) mFirstFinger.resetTargetPoint();                    mSecondFinger = null;                }                if (mCallback != null)                {                    mCallback.onFingerEnd();                }                mPercent = 0;                break;            }        }        if (!mFingerTouchMode) // 如果是当前是多指滑动状态,拦截Touch事件,这里是没有调用super方法(不会分发该事件)        // onInterceptionTouchEvent 只能拦截当前是DOWN事件或者是FirstTouchTarget对象不为空的时候!什么时候不为空,还没有搞明白!        {            super.dispatchTouchEvent(ev);        }        invalidate(); // 把移动轨迹在onDraw中画出来        return true;    }

xml布局

<com.neulion.android.dl.touchdemo.widget.DLMultipleFingerScrollLayout            android:id="@+id/dl_multiple_finger_layout"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:background="#ffffff">        <android.support.v7.widget.RecyclerView                android:id="@+id/recycler_view"                android:layout_width="match_parent"                android:layout_height="match_parent" />    </com.neulion.android.dl.touchdemo.widget.DLMultipleFingerScrollLayout>

具体的实现可以在GitHub上下载源码。


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 如果报到证丢了怎么办 考编报到证丢了怎么办 2017报到证丢了怎么办 携程机票不能退怎么办 暗黑3进度全没了怎么办 从飞机上掉下来怎么办? 白带多有酸臭味怎么办 私募基金跑路了怎么办 车险的保单丢了怎么办 做的3d有病毒怎么办 猫吐白沫没精神怎么办 光伏发电坏了怎么办 户户通违规移机怎么办 原岳阳恒立地块怎么办 发票打错一个字怎么办 香港自由行g签证怎么办 小米5铃声不响怎么办 德龙驾驶室爱跳怎么办 高低速的车换挡怎么办 挂车鞍座间隙大怎么办 自考本科证丢了怎么办 学籍号密码忘了怎么办 嘀嘀虎没流量了怎么办 被房产中介骗了怎么办 孕中期胎盘早剥怎么办 船用雷达不扫描怎么办? 招工年龄报小了怎么办 三茅hr app闪退怎么办 ipad开关键坏了怎么办 档案单位给丢了怎么办 单位把档案弄丢了怎么办 北京集体户口离职后怎么办 群面遇到辩论题怎么办 学校派遣证丢了怎么办 派遣证过期10年怎么办 中专派遣证丢了怎么办 档案派遣证丢了怎么办 毕业派遣证丢了怎么办 派遣证遗失五年怎么办 卵泡太大排不出来怎么办 撞了大使馆的车怎么办