android的简单手势监听一般用onTouchListner接口,复杂手势监听一般用Detector来接替onTouch的处理。

手势监听后的处理涉及android坐标系统的问题。

多点触点则一般用event.getPointerCount()获取目前的触摸点的个数,用event.getX(index)、event.getY(index)获得第index个触摸点的坐标。


一. 用View.OnTouchListener接口监听简单手势

在Android中,简单的手势监听用实现View类的View.OnTouchListener接口的方法即可

如,对某个view进行手势监听

RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.rlayout);relativeLayout.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:// 按下屏幕的操作break;case MotionEvent.ACTION_MOVE:// 在屏幕上移动的操作break;case MotionEvent.ACTION_UP:// 离开屏幕的操作break;case (MotionEvent.ACTION_CANCEL):// 手势撤消的操作// 一般认为不能由用户主动触发。// 系统在运行到一定程度下无法继续响应你的后续动作时会产生此事件break;default:break;}// 这个返回值如果是false的话,那么它只会接受到第一个ACTION_DOWN的效果,// 后面的它认为没有触发,所以要想继续监听后续事件,需要返回值为truereturn true;}});

需要注意的是,onTouch()方法要返回true,否则只会监听ACTION_DOWN

也可以对整个Activity进行监听,如:

public class MyActivity extends Activity {private static final String DEBUG_TAG = "MyActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}@Overridepublic boolean onTouchEvent(MotionEvent event) {int action = MotionEventCompat.getActionMasked(event);switch (action) {case (MotionEvent.ACTION_DOWN):Log.d(DEBUG_TAG, "Action was DOWN");break;case (MotionEvent.ACTION_MOVE):Log.d(DEBUG_TAG, "Action was MOVE");break;case (MotionEvent.ACTION_UP):Log.d(DEBUG_TAG, "Action was UP");break;case (MotionEvent.ACTION_CANCEL):Log.d(DEBUG_TAG, "Action was CANCEL");break;default:break;}return true;}}

二. 用GestureDetector监听复杂手势

对于复杂手势的监听,一般用GestureDetector,而且为了提高版本的兼容,一般用support.v4中的GestureDetectorCompat

如:对某个view进行手势监听

package com.example.touch;import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.GestureDetectorCompat;
import android.util.Log;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.LinearLayout;public class MyActivity2 extends Activity {private static final String TAG = "MyActivity2";// 用GestureDetectorCompat替换GestureDetector,GestureDetectorCompat兼容的版本较广private GestureDetectorCompat mDetector;private LinearLayout linearLayout;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();initDetector();setTouchListener();}// 对linearLayout设置手势监听private void setTouchListener() {linearLayout.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {mDetector.onTouchEvent(event);return true;}});}// // 让GestureDetectorCompat来接替处理// @Override// public boolean onTouchEvent(MotionEvent event){// this.mDetector.onTouchEvent(event);// // Be sure to call the superclass implementation// return super.onTouchEvent(event);// }private void initView() {linearLayout = (LinearLayout) findViewById(R.id.linearlayout);}// 初始化手势监听器Detectorprivate void initDetector() {mDetector = new GestureDetectorCompat(MyActivity2.this,new MytGestureListener());}/*** 手势监听器*/private class MytGestureListener extends SimpleOnGestureListener {// Touch down时触发@Overridepublic boolean onDown(MotionEvent e) {Log.d(TAG, "onDown");return super.onDown(e);}// 在Touch down之后一定时间(115ms)触发@Overridepublic void onShowPress(MotionEvent e) {Log.d(TAG, "onShowPress");}// 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发@Overridepublic boolean onSingleTapUp(MotionEvent e) {Log.d(TAG, "onSingleTapUp");return super.onSingleTapUp(e);}// 滑动时触发@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY) {Log.d(TAG, "onScroll");return super.onScroll(e1, e2, distanceX, distanceY);}// 抛掷// 滑动一段距离,up时触发@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {Log.d(TAG, "onFling");return super.onFling(e1, e2, velocityX, velocityY);}// 长按后触发(Touch down之后一定时间(500ms))@Overridepublic void onLongPress(MotionEvent e) {Log.d(TAG, "onLongPress");}}}

对整个Activity进行监听

package com.example.touch;import android.app.Activity;
import android.os.Bundle;
import android.support.v4.view.GestureDetectorCompat;
import android.util.Log;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.widget.LinearLayout;public class MyActivity2 extends Activity {private static final String TAG = "MyActivity2";// 用GestureDetectorCompat替换GestureDetector,GestureDetectorCompat兼容的版本较广private GestureDetectorCompat mDetector;private LinearLayout linearLayout;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();initDetector();// setTouchListener();}// // 对linearLayout设置手势监听// private void setTouchListener() {// linearLayout.setOnTouchListener(new OnTouchListener() {// @Override// public boolean onTouch(View v, MotionEvent event) {// mDetector.onTouchEvent(event);// return true;// }// });// }// 让GestureDetectorCompat来接替处理@Overridepublic boolean onTouchEvent(MotionEvent event) {this.mDetector.onTouchEvent(event);// Be sure to call the superclass implementationreturn super.onTouchEvent(event);}private void initView() {linearLayout = (LinearLayout) findViewById(R.id.linearlayout);}// 初始化手势监听器Detectorprivate void initDetector() {mDetector = new GestureDetectorCompat(MyActivity2.this,new MytGestureListener());}/*** 手势监听器*/private class MytGestureListener extends SimpleOnGestureListener {// Touch down时触发@Overridepublic boolean onDown(MotionEvent e) {Log.d(TAG, "onDown");return super.onDown(e);}// 在Touch down之后一定时间(115ms)触发@Overridepublic void onShowPress(MotionEvent e) {Log.d(TAG, "onShowPress");}// 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发@Overridepublic boolean onSingleTapUp(MotionEvent e) {Log.d(TAG, "onSingleTapUp");return super.onSingleTapUp(e);}// 滑动时触发@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY) {Log.d(TAG, "onScroll");return super.onScroll(e1, e2, distanceX, distanceY);}// 抛掷// 滑动一段距离,up时触发@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {Log.d(TAG, "onFling");return super.onFling(e1, e2, velocityX, velocityY);}// 长按后触发(Touch down之后一定时间(500ms))@Overridepublic void onLongPress(MotionEvent e) {Log.d(TAG, "onLongPress");}// 双击@Overridepublic boolean onDoubleTap(MotionEvent e) {Log.d(TAG, "onDoubleTap");return super.onDoubleTap(e);}}}

要点是: 创建一个手势监听器如MyGestureListener继承自SimpleOnGestureListener,

private class MytGestureListener extends SimpleOnGestureListener 

再用MyGestureListener初始化Detetor对象mDetector,

 // 初始化手势监听器Detectorprivate void initDetector() {mDetector = new GestureDetectorCompat(MyActivity2.this,new MytGestureListener());}

然后让mDetector来接替处理手势监听

 // 让GestureDetectorCompat来接替处理@Overridepublic boolean onTouchEvent(MotionEvent event){this.mDetector.onTouchEvent(event);// Be sure to call the superclass implementationreturn super.onTouchEvent(event);}

三. onFling() 的使用

filing手势在android交互设计中应用非常广泛:电子书的滑动翻页、ListView滑动删除item、滑动解锁等。所以如何检测用户的fling手势是非常重要的。

OnFling的四个参数意思分别为

e1: The first down motion event that started the fling.手势起点的移动事件
e2: The move motion event that triggered the current onFling.当前手势点的移动事件
velocityX: The velocity of this fling measured in pixels per second along the x axis.每秒x轴方向移动的像素
velocityY: The velocity of this fling measured in pixels per second along the y axis.每秒y轴方向移动的像素

说的更简单点就是,鼠标手势相当于一个向量(当然有可能手势是曲线),e1为向量的起点,e2为向量的终点,velocityX为向量水平方向的速度,velocityY为向量垂直方向的速度

if (e1.getX() - e2.getX() > verticalMinDistance && Math.abs(velocityX) > minVelocity)

则上面的语句能知道啥意思了吧,就是说向量的水平长度(滑了有多长)必须大于 verticalMinDistance,并且水平方向速度大于 minVelocity。

onScroll则与之类似,e1为手势起点事件,e2为手势终点事件,distanceX为e1与e2在x轴的差(带正负),distanceY为e1与e2在y轴的差(带正负)

四. Android中的坐标系统
首先明确一下 android中的坐标系统 :屏幕的左上角是坐标系统原点(0,0),原点向右延伸是X轴正方向,原点向下延伸是Y轴正方向

1、手势处理中常用到的几个函数:

View的getTop()、getBottom(),getLeft(),getRight()得到的坐标是相对父容器视图而言的

而motionEvent的getRawX(),getRawY是相对屏幕而言的,getX(),getY()则是相对touch事件的控件而言的

2、屏幕的宽和高

为了在屏幕中的合适位置绘制图形,我们需要使用屏幕的宽和高作为参考,来确定绘制图形的位置。要获得屏幕的宽和高,首先从Activity对象中获得WindowManager对象,然后从WindowManager对象中获得Display对象,再从Display对象中获得屏幕的宽和高。
// 获得屏幕的宽和高
WindowManager manger = getWindowManager();
Diaplay diaplay = manager.getDefaultDisplay();
int screenWidth = display.getWidth();
int screenHeight = display.getHeight();
五、多点触摸事件
参考:http://blog.csdn.net/scarthr/article/details/42437209
获取多个触摸点时,可以调用event.getPointerCount()获取目前的触摸点的个数。要获取某个触摸点,使用event.getX(index)、event.getY(index)获得第index个触摸点的坐标。

缩放图片

根据两点间的距离的变化就可以检测出两点操作是放大的手势还是缩小的手势:

[java] view plaincopy
  1. package com.example.testtouch;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.view.MotionEvent;
  5. import android.view.View;
  6. import android.view.View.OnTouchListener;
  7. import android.widget.ImageView;
  8. import android.widget.RelativeLayout;
  9. import android.widget.RelativeLayout.LayoutParams;
  10. public class MainActivity extends Activity {
  11. private RelativeLayout rl;
  12. private ImageView iv;
  13. private double lastDistance;
  14. private double currentDistance;
  15. private double scale = 1;
  16. @Override
  17. protected void onCreate(Bundle savedInstanceState) {
  18. super.onCreate(savedInstanceState);
  19. setContentView(R.layout.activity_main);
  20. rl = (RelativeLayout) findViewById(R.id.rl);
  21. iv = (ImageView) findViewById(R.id.iv);
  22. rl.setOnTouchListener(new OnTouchListener() {
  23. @Override
  24. public boolean onTouch(View v, MotionEvent event) {
  25. switch (event.getAction()) {
  26. case MotionEvent.ACTION_DOWN:
  27. break;
  28. case MotionEvent.ACTION_MOVE:
  29. LayoutParams lp = (LayoutParams) iv.getLayoutParams();
  30. if (event.getPointerCount() == 2) {
  31. currentDistance = getDistance(
  32. event.getX(0) - event.getX(1), event.getY(0)
  33. - event.getY(1));
  34. if (currentDistance - lastDistance >= 5) {
  35. // 放大
  36. scale *= 1.1;
  37. if (scale >= 4) {
  38. scale = 4;
  39. } else {
  40. lp.width = (int) (1.1f * iv.getWidth());
  41. lp.height = (int) (1.1f * iv.getHeight());
  42. iv.setLayoutParams(lp);
  43. }
  44. } else if (lastDistance - currentDistance >= 5) {
  45. // 缩小
  46. scale *= 0.9;
  47. if (scale <= 1) {
  48. scale = 1;
  49. } else {
  50. lp.width = (int) (0.9f * iv.getWidth());
  51. lp.height = (int) (0.9f * iv.getHeight());
  52. iv.setLayoutParams(lp);
  53. }
  54. }
  55. lastDistance = currentDistance;
  56. }
  57. break;
  58. case MotionEvent.ACTION_UP:
  59. break;
  60. default:
  61. break;
  62. }
  63. return true;
  64. }
  65. });
  66. }
  67. /**
  68. * 计算两点间距离
  69. *
  70. * @param x
  71. * @param y
  72. * @return
  73. */
  74. private double getDistance(double x, double y) {
  75. return Math.sqrt(x * x + y * y);
  76. }
  77. }

Android 手势监听学习总结相关推荐

  1. android 手势监听案例

    class MyGestureListener implements GestureDetector.OnGestureListener {@Overridepublic boolean onDown ...

  2. android手势监听功能吗,Android手势监听 OnGestureListener (短按,长按,慢滑动,快滑动)...

    /** * @以下方法中的参数解释: * @e1:第1个是 ACTION_DOWN MotionEvent 按下的动作 * @e2:后一个是ACTION_UP MotionEvent 抬起的动作(这里 ...

  3. Android 触摸屏交互之手势监听

    效果图 前言 2020年,智能手机大行其道,相信不会还有人用着老式的按键手机了吧,而智能手机最大的交互就是手机屏幕,其次的就是音量操作.生物识别(指纹+人脸+瞳孔).说白了用的最多的是手机的屏幕,屏幕 ...

  4. Android——滑动监听SwipeRefreshLayout+瀑布流Recycl+Butter自动生成

    Android--滑动监听SwipeRefreshLayout+瀑布流Recycl+Butter自动生成 package c.example.jreduch09;import android.os.A ...

  5. Android监听左右滑删除通知,Android 滑动监听RecyclerView线性流+左右划删除+上下移动...

    废话不多说了,直接给大家贴代码了.具体代码如下所示: xmlns:tools="http://schemas.android.com/tools" android:layout_w ...

  6. Android 监听 Android中监听系统网络连接打开或者关闭的实现代码

    本篇文章对Android中监听系统网络连接打开或者关闭的实现用实例进行了介绍.需要的朋友参考下 很简单,所以直接看代码 复制代码 代码如下: package xxx; import android.c ...

  7. Android RecyclerView 监听滑动

    今天,简单讲讲Android 如何监听滑动. 不废话了,主要是需要做一个功能,实现RecyclerView滑动时,让一个标题栏固定显示在顶部. 基本知识: 列表的滚动一般分为两种: 手指按下 -> ...

  8. android 如何监听应用前后台切换

    今天,简单讲讲android如何判断应用切换到后台和应用切换到前台. 这个其实很简单,之前需要做一个功能,当app由后台进入前台时需要完成一些逻辑操作,所以在网上查找如何判断app由后台进入前台,最终 ...

  9. java edittext 输入监听_Android应用开发之Android EditText 监听用户输入完成的实例

    本文将带你了解Android应用开发Android EditText 监听用户输入完成的实例,希望本文对大家学Android有所帮助. 我们都知道, Android   EditText输入框,并没有 ...

最新文章

  1. vector,数组,动态数组效率测试
  2. CMD命令,常驻内存的与外部的介绍 还有CMD格式化
  3. java中的快速生成代码
  4. [转]在Fedora上安装Oracle 11g XE
  5. (四)建筑物多边形化简系统——“去尾巴”和分割复杂多边形
  6. 目标检测领域还有什么可做的?19 个方向给你建议
  7. Vue安装jquery插件
  8. 这代码她不美吗?——试题 基础练习 十六进制转八进制
  9. Your PC needs to be repaired
  10. svn提交时自动设置 needs-lock
  11. add git 指定类型文件夹_UE4 使用git配合远程仓库
  12. dependency报红_解决IDEA中Maven依赖包导入失败报红问题(总结最有效8种解决方案)...
  13. Java命令行界面(第26部分):CmdOption
  14. 论文笔记(Neural Graph Collaborative Filtering)
  15. FreeModbus线圈
  16. python求1到n的乘积_Python如何计算列表中所有数字的乘积?(代码示例)
  17. oracle 11g 延迟验证,取消 11G延迟密码验证
  18. Java中HashMap和TreeMap的区别深入理解,java开发面试笔试题
  19. Access数据库问题锦集
  20. SPOJ DQUERY D-query--线段树解法

热门文章

  1. 南宁陶粒之慢性病监测信息管理系统功能技术分享
  2. IEO调查回顾:87个项目,募资20亿,62%破发,最高亏损99%
  3. 爬取网易云音乐排行--2(抓包、forma、反爬)
  4. toast 技术之一
  5. 类记事本字处理软件java_基于Java的记事本程序的设计与实现.doc
  6. centos7使用testdisk7.1恢复误删除的文件,要求给出详细可行的教程详细并说明注意点...
  7. 拉伯证券|A股涨势趋缓,个股分化,北向资金继续“买买买”
  8. OpenXML方式导出word
  9. Linux Kdump内核崩溃转储部署详解
  10. linux 常用命令搜集 —— 筑梦之路