博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android手势监听类GestureDetector的使用
阅读量:6693 次
发布时间:2019-06-25

本文共 6123 字,大约阅读时间需要 20 分钟。

hot3.png

在使用自定义视图的时候,对触屏事件的处理是比不可少的,有能力的可以自己写代码处理,这样更加的灵活。如果不想这么麻烦,Android提供了一个手势监听类GestureDetector,可以供我们使用。GestureDetector使用很方便,提供了单击,双击,长按等操作的处理,但是一般的定义界面都比较复杂,还用很多需要注意的地方,在这儿总结一下GestureDetector的使用。

首先新建一个空白的工程,主界面的layout中只需要添加一个按钮就行

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

  2.     xmlns:tools="http://schemas.android.com/tools"

  3.     android:layout_width="match_parent"

  4.     android:layout_height="match_parent"

  5.     android:paddingBottom="@dimen/activity_vertical_margin"

  6.     android:paddingLeft="@dimen/activity_horizontal_margin"

  7.     android:paddingRight="@dimen/activity_horizontal_margin"

  8.     android:paddingTop="@dimen/activity_vertical_margin"

  9.     tools:context=".MainActivity" >

  10.     <Button

  11.         android:id="@+id/btn_textgesture"

  12.         android:layout_width="fill_parent"

  13.         android:layout_height="fill_parent"

  14.         android:text="@string/app_name" />

  15. </RelativeLayout>

复制代码

由于要测试的触屏事件,所有这个按钮比较大,主界面为如下效果: 25164146_GmsG.jpg首先介绍一下触屏事件处理的基本思路。触屏一般有三个基本事件,down按下,move移动,up离开,通过对这三个基本事件的监听,判断用户执行了何种操作。一个标准的触屏操作一般都是一系列基本事件的组合,在Android的框架中,通过onTouch()函数可以获取基本的触屏事件,而像onClick这样的函数,已经是一系列基本事件的组合。比如,发生了Down事件,在up事件之前没有发生move事件,或者move的范围很小,并且down事件和up事件的间隔很短,这就是一个click或者singelTap事件,对比实体键盘按键的事件,实体键盘是在down事件发生后进行操作,而触屏事件一般是up事件发生后进行操作。下面是activity的代码

  1. package com.example.testgesture;

  2. import android.app.Activity;

  3. import android.os.Bundle;

  4. import android.util.Log;

  5. import android.view.GestureDetector;

  6. import android.view.GestureDetector.SimpleOnGestureListener;

  7. import android.view.MotionEvent;

  8. import android.view.View;

  9. import android.view.View.OnTouchListener;

  10. import android.widget.Button;

  11. public class MainActivity extends Activity {

  12.     private Button mButton;

  13.     private GestureDetector mGestureDetector;

  14.     @Override

  15.     protected void onCreate(Bundle savedInstanceState) {

  16.         super.onCreate(savedInstanceState);

  17.         setContentView(R.layout.activity_main);

  18.         mGestureDetector = new GestureDetector(this, new MyOnGestureListener());

  19.         mButton = (Button) findViewById(R.id.btn_textgesture);

  20.         mButton.setOnTouchListener(new OnTouchListener() {

  21.             @Override

  22.             public boolean onTouch(View v, MotionEvent event) {

  23.                 Log.i(getClass().getName(), "onTouch-----" + getActionName(event.getAction()));

  24.                 mGestureDetector.onTouchEvent(event);

  25.                 // 一定要返回true,不然获取不到完整的事件

  26.                 return true;

  27.             }

  28.         });

  29.     }

  30.     private String getActionName(int action) {

  31.         String name = "";

  32.         switch (action) {

  33.             case MotionEvent.ACTION_DOWN: {

  34.                 name = "ACTION_DOWN";

  35.                 break;

  36.             }

  37.             case MotionEvent.ACTION_MOVE: {

  38.                 name = "ACTION_MOVE";

  39.                 break;

  40.             }

  41.             case MotionEvent.ACTION_UP: {

  42.                 name = "ACTION_UP";

  43.                 break;

  44.             }

  45.             default:

  46.             break;

  47.         }

  48.         return name;

  49.     }

  50.     class MyOnGestureListener extends SimpleOnGestureListener {

  51.         @Override

  52.         public boolean onSingleTapUp(MotionEvent e) {

  53.             Log.i(getClass().getName(), "onSingleTapUp-----" + getActionName(e.getAction()));

  54.             return false;

  55.         }

  56.         @Override

  57.         public void onLongPress(MotionEvent e) {

  58.             Log.i(getClass().getName(), "onLongPress-----" + getActionName(e.getAction()));

  59.         }

  60.         @Override

  61.         public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

  62.             Log.i(getClass().getName(),

  63.                     "onScroll-----" + getActionName(e2.getAction()) + ",(" + e1.getX() + "," + e1.getY() + ") ,("

  64.                             + e2.getX() + "," + e2.getY() + ")");

  65.             return false;

  66.         }

  67.         @Override

  68.         public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

  69.             Log.i(getClass().getName(),

  70.                     "onFling-----" + getActionName(e2.getAction()) + ",(" + e1.getX() + "," + e1.getY() + ") ,("

  71.                             + e2.getX() + "," + e2.getY() + ")");

  72.             return false;

  73.         }

  74.         @Override

  75.         public void onShowPress(MotionEvent e) {

  76.             Log.i(getClass().getName(), "onShowPress-----" + getActionName(e.getAction()));

  77.         }

  78.         @Override

  79.         public boolean onDown(MotionEvent e) {

  80.             Log.i(getClass().getName(), "onDown-----" + getActionName(e.getAction()));

  81.             return false;

  82.         }

  83.         @Override

  84.         public boolean onDoubleTap(MotionEvent e) {

  85.             Log.i(getClass().getName(), "onDoubleTap-----" + getActionName(e.getAction()));

  86.             return false;

  87.         }

  88.         @Override

  89.         public boolean onDoubleTapEvent(MotionEvent e) {

  90.             Log.i(getClass().getName(), "onDoubleTapEvent-----" + getActionName(e.getAction()));

  91.             return false;

  92.         }

  93.         @Override

  94.         public boolean onSingleTapConfirmed(MotionEvent e) {

  95.             Log.i(getClass().getName(), "onSingleTapConfirmed-----" + getActionName(e.getAction()));

  96.             return false;

  97.         }

  98.     }

  99. }

复制代码

首先是声明一个GestureDetector,然后重写Button的onTouch函数,将触屏事件交给GestureDetector处理。
首先做一个对按钮做一个单击  
25164146_Q6bg.jpgonSingleTapUp被调用,说明发生了单击事件,onSingleTapConfirmed被调用,说明确认发生了一个单击事件,不是双击的事件。需要注意的是onSingleTapUp已经是一click事件,onSingleTapUp触发的时候是
ACTION_UP事件。onSingleTapConfirmed是在用户手指
离开屏幕后触发,所有up并不是所有触屏事件的结束。
做一个双击的操作
25164146_wlLX.jpg  首先发生了一个onSingleTapUp,说明完成了一次单击事件,然后发生了onDoubleTap,至此,一次双击事件已经完成。我们可以看到,onDoubleTap发生的时候是
ACTION_DOWN事件,也就是说双击事件是第二次按下屏幕的时候触发,而不是第二次离开屏幕的时候触发,在onDoubleTap发生之后,就可以在onDoubleTapEvent中监听到双击事件发生后从按下到弹起的所有触屏事件。onDoubleTap发生后不会触发onSingleTapUp和onSingleTapConfirmed。
做一个长按的操作
25164146_2u6m.jpg  onLongPress实在
ACTION_DOWN时发生,onLongPress发生后在up之前不会用其他事件触发,可以在
onShowPress处理状态的改变,比如按钮的按下状态。
做一个滑动操作
25164146_M1cK.jpgonScroll事件是拖动,onFling是抛。结合log来了解一下。首先是ACTION_DOWN,之后多次ACTION_MOVE,移动超过一定距离,触发了onScroll,如果onScroll被触发,
在up之前是不会有长按,单击,双击等事件的。看一下onScroll的参数
  1. public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)

复制代码

e1为第一次按下的事件,和onDown事件里面的一样,e2为当前的事件,distanceX为本次onScroll移动的X轴距离,distanceY为移动的Y轴距离,移动的距离是相对于上一次onScroll事件的移动距离,而不是当前点和按下点的距离。这次滑动最后触发了onFling事件,但是onFling事件的触发不是一定的,onFling是在ACTION_UP触发,平时列表在离开屏幕是继续滚动,就是通过这种方式触发。
  1. public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)

复制代码

onFling的前两个参数和onScroll相同,e2为用户拖动完离开屏幕时的点。veloctiyX,velocitY为离开屏幕时的初始速度,以这两个速度为初始速度做匀减速运动,就是现在拖动列表和拖动图片的各种缓存滚动的效果。
函数的返回值除了onLongPress,这些函数都是有返回值的,
  1. mButton.setOnTouchListener(new OnTouchListener() {

  2.             @Override

  3.             public boolean onTouch(View v, MotionEvent event) {

  4.                 Log.i(getClass().getName(), "onTouch-----" + getActionName(event.getAction()));

  5.                 mGestureDetector.onTouchEvent(event);

  6.                 // 一定要返回true,不然获取不到完整的事件

  7.                 return true;

  8.             }

  9.         });

复制代码

这些返回值会通过 mGestureDetector.onTouchEvent(event); 传递给onTouch。
最后总结一下GestureDetector结合SimpleOnGestureListener可以很方便的获取到单击,双击,长按等事件,但是对这些事件的处理不是简单的在对应的函数里做一些操作就可以的,复杂的自定义视图还是要在onTouch里面进行判断个个控件的焦点状态,而且GestureDetector也不是万能的,你如果要处理长按之后的移动,就要费一番功夫了,以为GestureDetector在长按发生后是不会在有onScroll的,你只能通过onTouch里面的ACTION_MOVE处理。

转载于:https://my.oschina.net/yuanxulong/blog/318588

你可能感兴趣的文章
Spring Boot 参考指南(开发Web应用程序)
查看>>
策略模式总结
查看>>
javascript块级作用域处理闭包和释放内存的垃圾回收
查看>>
快速入门React
查看>>
正则表达式语法入门
查看>>
关于顶级、一级、二级域名如何理解?
查看>>
图解CRM(客户关系管理)全流程
查看>>
微信小程序开发BUG经验总结
查看>>
Python学习--最完整的基础知识大全
查看>>
自定义组件间通信
查看>>
记录一个未解决的错误
查看>>
Laravel 5.6 正式发布(文档翻译工作将在春节后启动)
查看>>
兼容浏览器原生DOM的各种特性总结
查看>>
第一个GUI程序
查看>>
解析hierarchical.py from sklearn
查看>>
推荐引擎
查看>>
Mac版:上传图片到远程图床哪家强?
查看>>
Android学习系列-----2 Activity的生命周期与启动模式
查看>>
前端真的能做到彻底权限控制吗?
查看>>
EdgeX Foundry边缘计算框架-核心服务层
查看>>