Android攻城狮GestureDetector和GestureOverlayView

手势识别
可以通过以下两种方式实现:
1. 使用GestureDetector
2. 使用GestureOverlayView(属于线程的控件)

手势交互过程(原理):
1. 触屏一刹那,触发 MotionEvent 事件;
2. 被 OnTouchListener 监听,在 onTouch()中获得 MotionEvent对象;
3. GestureDetector 转发 MotionEvent 对象至 OnGestureListener;
4. OnGestureListener 获取该对象,根据该对象封装的信息做出合适的反馈;

MotionEvent:
1. 用于封装手势、触摸笔、轨迹球等动作事件;
2. 内部封装用于记录横轴和纵轴坐标的属性X和Y。
GestureDetector:
识别各种手势。
OnGestureListener:
1. 手势交互的监听接口,其提供多个抽象方法;
2. 根据 GestureDetector 的手势识别结果,调用相应的方法。

GestureDetector 详解:
触摸屏:按下、移动、抬起等。
监听触摸事件:重载 onTouch 或者设置 setOnTouchListener
GestureDetector 工作原理:
1. 当接收到用户触摸消息时,将消息交给 GestureDetector加工;
2. 通过设置监听器获得 GestureDetector 处理后的手势。
GestureDetector提供两个监听器:
1. OnGestureListener:处理单击类消息
2. OnDoubleTapListener:处理双击类消息

OnGestureListener接口的6个方法:
单击:onDown(MotionEvent e)
抬起:onSingleTapUp(MotionEvent e)
短按:onShowPress(MotionEvent e)
长按:onLongPress(MotionEvent e)
滚动:onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float disanceY)
滑动:onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
(注解:velocity:速率,速度)

OnDoubleTapListener接口的3个方法:
双击:onDoubleTap(MotionEvent e)
双击按下和抬起各触发一次:onDoubleTapEvent(MotionEvent e)
单击确认:onSingleTapConfirmed(MotionEvent e)就是很快地按下并抬起,但不连续点击第二下。

如果分别去实现这两个接口的所有方法,未免太麻烦了,所以这里提供了另一个接口:SimpleOnGestureListener,它已经继承了前面所讲的两个监听器。
- 继承SimpleOnGestureListener
- 重载感兴趣的手势
 1 public class MainActivity extends Activity {
 2     ImageView imageView;
 3     GestureDetector myDetector;
 4 
 5     class myGestureListenner extends SimpleOnGestureListener {
 6         @Override
 7         // e1表示起始事件,e2表示末尾事件,每个事件都含有坐标属性。通过起止事件的相对位置,可以判断是从左往右滑动还是从右往左滑动。
 8         public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
 9                 float velocityY) {
10             // TODO Auto-generated method stub
11             if (e1.getX() - e2.getX() > 50) {
12                 Toast.makeText(MainActivity.this, "从右边往左边滑动!", 0).show();
13 
14             } else if (e2.getX() - e1.getX() > 50) {
15                 Toast.makeText(MainActivity.this, "从左边往右边滑动!", 0).show();
16             }
17             return super.onFling(e1, e2, velocityX, velocityY);
18         }
19 
20     }
21 
22     @Override
23     protected void onCreate(Bundle savedInstanceState) {
24         super.onCreate(savedInstanceState);
25         setContentView(R.layout.fragment_main);
26         imageView = (ImageView) findViewById(R.id.image);
27         myDetector = new GestureDetector(new myGestureListenner());
28         imageView.setOnTouchListener(new OnTouchListener() {
29 
30             @Override
31             public boolean onTouch(View v, MotionEvent event) {
32                 // TODO Auto-generated method stub
33                 // 捕获触摸屏幕的Event事件
34                 myDetector.onTouchEvent(event);
35 
36                 return true;
37             }
38         });
39     }
40 
41 }
使用GestureOverlayView进行手势识别的步骤:
1. 使用Gesture Builder生成手势文件
2. 将文件加入到项目
3. 在项目中创建 GestureOverlayView,将它放置在想要识别手势的控件上,或者把它包裹起来。

只能识别文件中存在的手势,如果不是文件中存在的手势,就无法识别。
---------------
在res文件夹下创建文件夹raw,把手势文件gesture添加到这里。
GestureOverlayView
一种用于手势输入的透明覆盖层,可覆盖在其他控件的上方,也可以包含其他控件。存在3个监听接口:
GestureOverlayView.OnGestureListener    // 手势监听器
GestureOverlayView.OnGesturePerformedListener    // 手势执行监听器
GestureOverlayView.OnGesturingListener    // 手势执行中监听器
------------------
如图使用GestureOverlayView控件去包含ImageView控件。
可识别手势的区域大小不是由ImageView决定,而是由GestureOverlayView决定。
------------------------
补充:
使用Android Studio则更加简单,不用去创建 Simple Project。老师之所以要创建Simple Project,是因为模拟器中没有Gesture Builder这种应用,所以要自己创建。而Android Studio的模拟器是有Gesture Builder的,所以我们可以直接进入模拟器,点击Gesture Builder图标,进行手势的创建。

给gestureOverlayView设置监听器:
gestureOverlayView.addOnGesturePerformedListener(new OnGesturePerformedListener(){})
重写方法onGesturePerformed()。
如图,onGesturePerformed()的示例代码,也就是关于手势识别的代码实现。
ArrayList<Prediction>:预测集
predction.score:相似度,值越大,则越相似,也就是说你必须做出几乎一模一样的手势才能通过识别。相似度的取值范围一般是0.0~10.0,取10.0就已经太夸张了,因为很难做出非常接近的手势。所以,这里的下限只取5.0:
predction.score>=5.0
如果觉得显示的手势的轨迹不好看,可以自定义轨迹的样式。
一些常见的XML属性设置:
Android:eventInterceptionEnabled  定义当手势已经被识别出来时,是否拦截该手势动作
Android:fadeDuration  当用户画完的时候,手势效果淡出的时间
Android:fadeEnabled  用户画完之后,手势是否自动淡出
Android:gestureColor  手势的颜色
Android:gestureStrokeType  笔画的类型
Android:gestureStrokeWidth  笔画的粗细
 1 public class MainActivity extends ActionBarActivity {
 2     GestureOverlayView gestureOverlayView;
 3 
 4     @Override
 5     protected void onCreate(Bundle savedInstanceState) {
 6         super.onCreate(savedInstanceState);
 7         setContentView(R.layout.fragment_main);
 8         gestureOverlayView = (GestureOverlayView) findViewById(R.id.gestureOverlayView1);
 9         // 1.找到预设定的手势文件
10         // 2.加载那个手势文件中的所有手势
11         // 3.匹配,识别
12 
13         // 从资源中将手势库文件加载进来
14         final GestureLibrary library = GestureLibraries.fromRawResource(
15                 MainActivity.this, R.raw.gestures);
16         library.load();
17         gestureOverlayView
18                 .addOnGesturePerformedListener(new OnGesturePerformedListener() {
19 
20                     @Override
21                     public void onGesturePerformed(GestureOverlayView overlay,
22                             Gesture gesture) {
23                         // TODO Auto-generated method stub
24                         // 读出手势库中内容 识别手势
25                         ArrayList<Prediction> mygesture = library
26                                 .recognize(gesture);
27                         Prediction prediction = mygesture.get(0);
28                         if (prediction.score >= 5.0) {
29                             if (prediction.name.equals("exit")) {
30                                 finish();
31                             }
32                             if (prediction.name.equals("next")) {
33                                 Toast.makeText(MainActivity.this, "下一首", 0)
34                                         .show();
35                             }
36                             if (prediction.name.equals("previouse")) {
37                                 Toast.makeText(MainActivity.this, "上一首", 0)
38                                         .show();
39                             }
40                         } else {
41                             Toast.makeText(MainActivity.this, "没有该手势", 0)
42                                     .show();
43                         }
44 
45                     }
46                 });
47 
48     }
49 
50 }




原文地址:https://www.cnblogs.com/my334420/p/6754432.html