Gesture detector

  Android Touch Screen 与传统Click Touch Screen不同,会有一些手势(Gesture),例如Fling,Scroll等等。

  这些Gesture会使用户体验大大提升。Android中的Gesture识别(detector)是通过GestureDetector.OnGestureListener接口实现的。

  1. Android事件处理机制是基于Listener实现的,比如触摸屏相关的事件,就是通过onTouchListener实现;
  2. 所有View的子类都可以通过setOnTouchListener()、setOnKeyListener()等方法来添加对某一类事件的Listener;
  3. Listener一般会以Interface的方式来提供,其中包含一个或多个abstract方法,我们需要实现这些方法来完成onTouch()、onKey()等操作。这样,程序便可以在特定的事件被dispatch到该view的时候,通过callback函数给予适当的响应。

Touch Screen Click Demo

public class MyGesture extends Activity implements OnTouchListener
{
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView tv = (TextView) findViewById(R.id.tv);
tv.setOnTouchListener(this);
} public boolean onTouch(View v, MotionEvent event)
{
Toast.makeText(this, "Touch Touch", Toast.LENGTH_SHORT).show();
return false;
}
}

  可以通过MotionEvent的getAction()方法来获取Touch事件的类型,包括 ACTION_DOWN(按下触摸屏), ACTION_MOVE(按下触摸屏后移动受力点), ACTION_UP(松开触摸屏)和ACTION_CANCEL(不会由用户直接触发)。

  借助对于用户不同操作的判断,结合getRawX()、getRawY()、getX()和getY()等方法来获取坐标后,可以实现诸如拖动某一个按钮,拖动滚动条等功能。

detector Gesture

  这里需要GestureDetector.OnGestureListener接口的帮助

public class MyGesture extends Activity implements OnTouchListener, OnGestureListener
{
private GestureDetector mGestureDetector; public MyGesture()
{
mGestureDetector = new GestureDetector(this);
} public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView tv = (TextView) findViewById(R.id.tv);
tv.setOnTouchListener(this);
tv.setFocusable(true);
tv.setClickable(true);
tv.setLongClickable(true);
mGestureDetector.setIsLongpressEnabled(true);
} /*
* 在onTouch()方法中,我们调用GestureDetector的onTouchEvent()方法,
* 将捕捉到的MotionEvent交给GestureDetector 来分析是否有合适的callback函数来处理用户的手势
*/
public boolean onTouch(View v, MotionEvent event)
{
return mGestureDetector.onTouchEvent(event);
} // 用户轻触触摸屏,由1个MotionEvent ACTION_DOWN触发
public boolean onDown(MotionEvent arg0)
{
Log.i("MyGesture", "onDown");
Toast.makeText(this, "onDown", Toast.LENGTH_SHORT).show();
return true;
} /*
* 用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发
* 注意和onDown()的区别,强调的是没有松开或者拖动的状态
*/
public void onShowPress(MotionEvent e)
{
Log.i("MyGesture", "onShowPress");
Toast.makeText(this, "onShowPress", Toast.LENGTH_SHORT).show();
} // 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发
public boolean onSingleTapUp(MotionEvent e)
{
Log.i("MyGesture", "onSingleTapUp");
Toast.makeText(this, "onSingleTapUp", Toast.LENGTH_SHORT).show();
return true;
} // 用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
{
Log.i("MyGesture", "onFling");
Toast.makeText(this, "onFling", Toast.LENGTH_LONG).show();
return true;
} // 用户按下触摸屏,并拖动,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE触发
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
{
Log.i("MyGesture", "onScroll");
Toast.makeText(this, "onScroll", Toast.LENGTH_LONG).show();
return true;
} // 用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发
public void onLongPress(MotionEvent e)
{
Log.i("MyGesture", "onLongPress");
Toast.makeText(this, "onLongPress", Toast.LENGTH_LONG).show();
}
}

Fling detector

  除了第一个触发Fling的ACTION_DOWN和最后一个ACTION_MOVE中包含的坐标等信息外,还可以根据用户在X轴或者Y轴上的移动速度作为条件。

  比如下面的代码中就在用户移动超过100个像素,且X轴上每秒的移动速度大于200像素时才进行处理。

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
{
// 参数解释:
// e1:第1个ACTION_DOWN MotionEvent
// e2:最后一个ACTION_MOVE MotionEvent
// velocityX:X轴上的移动速度,像素/秒
// velocityY:Y轴上的移动速度,像素/秒 // 触发条件 :
// X轴的坐标位移大于FLING_MIN_DISTANCE,且移动速度大于FLING_MIN_VELOCITY个像素/秒 final int FLING_MIN_DISTANCE = 100, FLING_MIN_VELOCITY = 200;
if (e1.getX() - e2.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) > FLING_MIN_VELOCITY)
{
// Fling left
Log.i("MyGesture", "Fling left");
Toast.makeText(this, "Fling Left", Toast.LENGTH_SHORT).show();
} else if (e2.getX() - e1.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) > FLING_MIN_VELOCITY)
{
// Fling right
Log.i("MyGesture", "Fling right");
Toast.makeText(this, "Fling Right", Toast.LENGTH_SHORT).show();
}
return false;
}

  tv.setLongClickable( true )是必须的,因为 只有这样,view才能够处理不同于Tap(轻触)的hold(即ACTION_MOVE,或者多个ACTION_DOWN)

  同样可以通过layout定义中的android:longClickable来做到这一点。

SimpleOnGestureListener

public class MyGesture extends Activity implements OnTouchListener
{
private GestureDetector mGestureDetector; public MyGesture()
{
mGestureDetector = new GestureDetector(new MySimpleGesture());
} public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView tv = (TextView) findViewById(R.id.tv);
tv.setOnTouchListener(this);
tv.setFocusable(true);
tv.setClickable(true);
tv.setLongClickable(true);
} public boolean onTouch(View v, MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_UP)
{
Log.i("MyGesture", "MotionEvent.ACTION_UP");
}
return mGestureDetector.onTouchEvent(event);
} // SimpleOnGestureListener implements GestureDetector.OnDoubleTapListener,
// GestureDetector.OnGestureListener
private class MySimpleGesture extends SimpleOnGestureListener
{
// 双击的第二下Touch down时触发
public boolean onDoubleTap(MotionEvent e)
{
Log.i("MyGesture", "onDoubleTap");
return super.onDoubleTap(e);
} // 双击的第二下Touch down和up都会触发,可用e.getAction()区分
public boolean onDoubleTapEvent(MotionEvent e)
{
Log.i("MyGesture", "onDoubleTapEvent");
return super.onDoubleTapEvent(e);
} // Touch down时触发
public boolean onDown(MotionEvent e)
{
Log.i("MyGesture", "onDown");
return super.onDown(e);
} // Touch了滑动一点距离后,up时触发
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
{
Log.i("MyGesture", "onFling");
return super.onFling(e1, e2, velocityX, velocityY);
} // Touch了不移动一直Touch down时触发
public void onLongPress(MotionEvent e)
{
Log.i("MyGesture", "onLongPress");
super.onLongPress(e);
} // Touch了滑动时触发
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
{
Log.i("MyGesture", "onScroll");
return super.onScroll(e1, e2, distanceX, distanceY);
} /*
* Touch了还没有滑动时触发 (1)onDown只要Touch Down一定立刻触发 (2)Touch
* Down后过一会没有滑动先触发onShowPress再触发onLongPress So: Touch Down后一直不滑动,onDown
* -> onShowPress -> onLongPress这个顺序触发。
*/
public void onShowPress(MotionEvent e)
{
Log.i("MyGesture", "onShowPress");
super.onShowPress(e);
} /*
* 两个函数都是在Touch Down后又没有滑动(onScroll),又没有长按(onLongPress),然后Touch Up时触发
* 点击一下非常快的(不滑动)Touch Up: onDown->onSingleTapUp->onSingleTapConfirmed
* 点击一下稍微慢点的(不滑动)Touch Up:
* onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed
*/
public boolean onSingleTapConfirmed(MotionEvent e)
{
Log.i("MyGesture", "onSingleTapConfirmed");
return super.onSingleTapConfirmed(e);
} public boolean onSingleTapUp(MotionEvent e)
{
Log.i("MyGesture", "onSingleTapUp");
return super.onSingleTapUp(e);
}
}
}

【Android】Gesture Detector的更多相关文章

  1. 【Android】一种提高Android应用进程存活率新方法

    [Android]一种提高Android应用进程存活率新方法 SkySeraph Jun. 19st 2016 Email:skyseraph00@163.com 更多精彩请直接访问SkySeraph ...

  2. 【Android】Eclipse自动编译NDK/JNI的三种方法

    [Android]Eclipse自动编译NDK/JNI的三种方法 SkySeraph Sep. 18th  2014 Email:skyseraph00@163.com 更多精彩请直接访问SkySer ...

  3. 【Android】不依赖焦点和选中的TextView跑马灯

    前言 继承TextView,并仿照源码修改而来,主要是取消了焦点和选中了判断,也不依赖文本的宽度. 声明 欢迎转载,但请保留文章原始出处:) 博客园:http://www.cnblogs.com 农民 ...

  4. 【Android】Android 移动应用数据到SD

    [Android]Android 移动应用数据到SD 在应用的menifest文件中指定就可以了,在 <manifest> 元素中包含android:installLocation 属性, ...

  5. 【Android】如何快速构建Android Demo

    [Android]如何快速构建Android Demo 简介 在 Android 学习的过程中,经常需要针对某些项目来写一些测试的例子,或者在做一些 demo 的时候,都需要先写 Activity 然 ...

  6. 【Android】IntentService & HandlerThread源码解析

    一.前言 在学习Service的时候,我们一定会知道IntentService:官方文档不止一次强调,Service本身是运行在主线程中的(详见:[Android]Service),而主线程中是不适合 ...

  7. 【转】(转)【Android】Paint的效果研究

    转自:http://wpf814533631.iteye.com/blog/1847661 (转)[Android]Paint的效果研究 博客分类: android   在Paint中有很多的属性可以 ...

  8. 【Android】首次进入应用时加载引导界面

    参考文章: [1]http://blog.csdn.net/wsscy2004/article/details/7611529 [2]http://www.androidlearner.net/and ...

  9. 【Android】【录音】Android录音--AudioRecord、MediaRecorder

    [Android][录音]Android录音--AudioRecord.MediaRecorder Android提供了两个API用于实现录音功能:android.media.AudioRecord. ...

随机推荐

  1. [转载]Error starting Sun's native2ascii:

    原文地址:Error starting Sun's native2ascii:作者:大一吧浪 Error starting Sun's native2ascii: at org.apache.tool ...

  2. Java中timer的schedule()和schedualAtFixedRate()函数的区别

    本文主要讨论java.util.Timer的schedule(timerTask,delay,period)和scheduleAtFixedRate(timerTask,delay,period)的区 ...

  3. [转]webMethods公司简介

    原文链接 webMethods公司简介 webMethods,Inc.(美国纳斯达克股市上市代号:WEBM)为著名业务整合软件供应商之一.公司于1996年创立,总部位于美国佛吉尼亚州(Virginia ...

  4. java中enum的应用

    package com.demo; public enum TestEnum { A("hello"), B("world"); private String ...

  5. Converting REF CURSOR to PIPE for Performance in PHP OCI8 and PDO_OCI

    原文地址:https://blogs.oracle.com/opal/entry/converting_ref_cursor_to_pipe REF CURSORs are common in Ora ...

  6. MySql随手记要

    1. 显示当前正在执行的进程. SHOW FULL PROCESSLIST 2. 显示执行计划. EXPLAIN SQL语句. 3. 强制使用索个索引. 在表名后面接 FORCE INDEX(索引名称 ...

  7. XML 特殊字符处理

    在XML中,有一些符号作为XML 的标记符号,一些特定情况下,属性值必须带有这些特殊符号. 下面主要是讲解一些常用的特殊符号的处理 例一: 双引号的使用. 双引号作为XML 属性值的开始结束符号,因此 ...

  8. 【Servlet】Java Serlvet Listener 监听器

    Listener监听器 Servlet规范中定义的一种特殊的组件,用来监听Servlet容器产生的事件并进行相应的处理 容器产生的事件分类 - 生命周期相关的事件 - 设置和删除Attribute数据 ...

  9. solr 5.3.1安装配置

    1.下载Solr5.3.1 http://mirror.bit.edu.cn/apache/lucene/solr/5.3.1/ wget http://mirror.bit.edu.cn/apach ...

  10. C# 程序打包Release版本

    注意:DEBUG和RELEASE的区别,DEBUG下可以直接运行,而RELEASE不一定能直接运行,这并不是表示RELEASE版本有问题,而是表示两者需要操作不同.RELEASE版本要比DEBUG版本 ...