Android 手势
原文链接 https://jiedang.github.io/2015/12/17/Android%E6%89%8B%E5%8A%BF%E8%AF%A6%E8%A7%A3%E5%92%8C%E4%BD%BF%E7%94%A8.html
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。
手势
什么是手势
其实就是 onTouchEvent 中用,去识别判断出用户当前操作是个啥行为,是双击,长按,滑动,缩放,抛掷这些,然后做相应的操作,业务。
识别手势
- 如何确定手势操作时间 ?(长按多久,双击间隔多久)
- 如何确定手势距离 ?(移动长度大于多少算移动,小于多少算点击)
- 如何确定连续加速度 ?(滑动加减速,抛掷后续补全)
当然系统有在ViewConfiguration 里面有设定这些操作的默认值,但是自身去识别具体那个手势,处理,逻辑太复杂,庞大,划不来。
想明白手势,首先需要有基础的事件分发知识,知道VIEW TREE 对于事件的处理,怎么去持有消耗一个事件,避免使用时候出现,“为啥我这个手势没有被触发啊,没有回调啊?”这些问题。
系统提供方法
系统在API 1就添加了手势类GestureDetector 支持识别手势:
public interface OnGestureListener {
boolean onDown(MotionEvent e);
void onShowPress(MotionEvent e);
boolean onSingleTapUp(MotionEvent e);
boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);
void onLongPress(MotionEvent e);
boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
}
public interface OnDoubleTapListener {
boolean onSingleTapConfirmed(MotionEvent e);
boolean onDoubleTap(MotionEvent e);
boolean onDoubleTapEvent(MotionEvent e);
}
对于如何在ontouchEvent中判断出这些手势可以参考 grepcode中源码,不复杂,繁琐些。主要讲使用,
GestureDetector怎么用(listener方式)
- 添加回调listenter"OnGestureListener"或者“OnDoubleTapListener”根据需要监控的手势
在你自定的view的onToucheEvent调用对应listener类似
public boolean onTouchEvent( MotionEvent event ) { boolean gestureIntercept = mGestureDetector.onTouchEvent(event); return gestureIntercept || super.onTouchEvent( event ); }
根据你要监控手势的层级,在listener各层级手势中返回true(接受事件),比如你要监听双击,那想当然的单击时间就必须接受,以此类推。
tips: 有时候只是想简单的监控一个手势,实现"OnGestureListener"需要填写太多方法,感觉繁琐,系统有提供一个GestureDetector的内部类SimpleOnGestureListener已经实现了对应借口,简单的extends,复写相关方法就好了,代码量少很多。
GestureDetector怎么用(handler方式)
- 通过构造器添加handler。
- 在handler里面处理message
private static final int SHOW_PRESS = 1;
private static final int LONG_PRESS = 2;
private static final int TAP = 3;
这种方式用的很少,有特殊需求可以参考。
V4对于低版本的适配
可以参考系统V4对于低版本的实现 GestureDetectorCompat,(源码中以compat结尾的都是Android系统自身对于低版本的适配类),使用方式和GestureDetector一样,都是丢入一个"OnGestureListener"和“OnDoubleTapListener”回调。
- 奇怪的是GestureDetector API 1就添加了,为什么还有一个GestureDetectorCompat做版本适配尼,可能有更好的兼容,后面有发现补充
GestureDetectorCompat中包含两个子类,GestureDetectorCompatImplBase 和 GestureDetectorCompatImplJellybeanMr2,分别是适配低版本,和API 17以上的版本,前者是处理事件判断出对应手势,后者是使用GestureDetector来实现内部判断。后面开发中如果需要在手势中 做些特别处理,可以复制GestureDetectorCompatImplBase实现做基础,然后修改。
关于加速度 VelocityTracker使用
onTouchEvent中 初始化
if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } mVelocityTracker.addMovement(ev);
设置大小范围 可以参考
mMinimumFlingVelocity = ViewConfiguration.getMinimumFlingVelocity(); mMaximumFlingVelocity = ViewConfiguration.getMaximumFlingVelocity();
在onTouchEvent的ActionUp里面获取加速完后的XY移动量。
//计算 mVelocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity); //获取是那根手指和手指ID final int upIndex = ev.getActionIndex(); final int id1 = ev.getPointerId(upIndex); //获取加速完后的偏移量XY final float x1 = mVelocityTracker.getXVelocity(id1); final float y1 = mVelocityTracker.getYVelocity(id1);
缩放手势 ScaleGestureDetector
和GestureDetector实现完全相同,使用也一样,都有“OnScaleGestureListener”和“SimpleOnScaleGestureListener”,也在V4中有适配类 ScaleGestureDetectorCompat,参照GestureDetector使用学习就好了。