小狼驿站 2012-04-28
转自 http://mahaile.blog.51cto.com/2891586/831105
android的手势识别是android更人性化,让我们的操作更简单, 其实我们日常应用中不少地方都使用了手势识别方法 比如 2011年那么火的 愤怒的小鸟 中的 发射武器, uc 游览器 的左右滑动功能,这都是可以使用android的手势识别来实现。
如果想要实现提高我们app 的用户体验,更具有可操作性,那这时android的GestureDetector 就派上用场了 , 我们先开看看GestureDetector这个类的api 给我们提供了哪些操作
下面是GestureDetector 这个类的概括情况
根据 <a style="color: #006699;" href="http://api.apkbus.com/reference/android/view/MotionEvent.html"><strong>MotionEvent</strong></a>
事件检测各种手势. <a style="color: #006699;" href="http://api.apkbus.com/reference/android/view/GestureDetector.OnGestureListener.html"><strong>GestureDetector.OnGestureListener</strong></a>
回调函数用于通知用户发生的手势动作。该类仅处理 <a style="color: #006699;" href="http://api.apkbus.com/reference/android/view/MotionEvent.html"><strong>MotionEvent</strong></a>
事件中的触摸事件(不处理轨迹球事件)。 使用该类的方法如下:
1:首先需要在初始化的时候创建GestureDetector对象实例
下面看看摘自android 的api 的摘要
interface | GestureDetector.OnDoubleTapListener | The listener that is used to notify when a double-tap or a confirmed single-tap occur. |
interface | GestureDetector.OnGestureListener | The listener that is used to notify when gestures occur. |
class | GestureDetector.SimpleOnGestureListener | A convenience class to extend when you only want to listen for a subset of all the gestures. |
接口 OnDoubleTapListener 手势监听器 用于双击时发出通知
接口 OnGestureListener 手势监听器 用于发送手势操作时发生通知 如 拖动,长按,按下,弹起 等手势操作
类 SimpleOnGestureListener GestureDetector的扩展类 这个类的作用是当我们只想使用部分手势时, 而非全部的时候 就可以继承这个类
GestureDetector 还有几个公共方法 如下
boolean | isLongpressEnabled() 判定是否允许长点击 |
boolean | onTouchEvent(MotionEvent ev) 分析给定的动作事件,如果满足条件,就触发 <a style="color: #006699; text-decoration: none;" href="http://api.apkbus.com/reference/android/view/GestureDetector.OnGestureListener.html">GestureDetector.OnGestureListener</a> 中提供的回调函数。 |
void | setIsLongpressEnabled(boolean isLongpressEnabled) 设置是否允许长按。如果允许长按,当用户按下并保持按下状态时, 将收到一个长按事件,同时不再接收其它事件;如果禁用长按, 当用户按下并保持按下状态然后再移动手指时,将会接收到滚动事件。 长按默认为允许。 |
void | setOnDoubleTapListener(GestureDetector.OnDoubleTapListener onDoubleTapListener) 设置双击及其相关手势的监听器。 |
OnGestureListener 接口 的公共方法 如果你想在你的app view中实现下面这些手势操作的话 继承该接口 并实现下面这些方法即可
abstract boolean | onDown(MotionEvent e) 当轻触手势按下屏幕 时发生的事件. |
abstract boolean | onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) 快速滑动后抬起事件的通知. |
abstract void | onLongPress(MotionEvent e) 长按时的通知事件 |
abstract boolean | onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) 滑动屏幕时通知事件 为了方便提供了X轴和Y轴上的滚动距离. |
abstract void | onShowPress(MotionEvent e) 当用户长点击后抬起时通知事件 |
abstract boolean | onSingleTapUp(MotionEvent e) 当轻触手势抬起屏幕时发生的事件. |
OnDoubleTapListener 接口的公共方法
abstract boolean | onDoubleTap(MotionEvent e) 双击发生时的通知。 |
abstract boolean | onDoubleTapEvent(MotionEvent e) 双击手势过程中发生的事件,包括按下、移动和抬起事件。 |
abstract boolean | onSingleTapConfirmed(MotionEvent e) 发生确定的单击时执行。 与 |
在实际应用中 我们根据我们所需要的功能实现不同的接口 或者 继承自SimpleOnGestureListener 类 只实现部分个人需要的方法 就可以了
我们这一章就以 OnGestureListener 接口来做示例 看看 他是怎么使用的
直接看代码 GameSurfaceView类
package yxqz.com;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.SurfaceHolder.Callback;
import android.widget.Toast;
/**
* android 手势识别
* @author mahaile
*
*/
public class GameSurfaceView extends SurfaceView implements Callback,OnGestureListener{
private String TAG="GameView";
boolean flag; //线程标示位 当为false时停止刷新界面
SurfaceHolder surfaceHolder;
GameViewThread gameViewThread;
float x=0,y=0;
int stat=0; //手势识别状态标示
private GestureDetector gd; // 手势
Context context;
int width,height;
Bitmap bitmap_role;
public GameSurfaceView(Context context) {
super(context);
this.context=context;
surfaceHolder=this.getHolder();
surfaceHolder.addCallback(this); //添加回调
//设置焦点 如果不设置焦点的话 在该界面下 点击触摸屏是无效的 默认为false
setFocusableInTouchMode(true);
bitmap_role=BitmapFactory.decodeResource(getResources(), R.drawable.role);
gd=new GestureDetector(this); //创建手势监听对象
}
public void onDraw(Canvas canvas){
canvas.drawColor(Color.BLACK);
//canvas.drawBitmap(bitmap_role, width/2-bitmap_role.getWidth()/2, y, null);
canvas.drawBitmap(bitmap_role, x-bitmap_role.getWidth()/2, y-bitmap_role.getHeight()/2, null);
}
//重写父类中的 onTouchEvent就可以监听到 触摸事件了 记住要设置焦点喔
@Override
public boolean onTouchEvent(MotionEvent event) {
gd.onTouchEvent(event); //通知手势识别方法
return true;
}
public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
}
public void surfaceCreated(SurfaceHolder surfaceHolder) {
//获取屏幕的 宽高 只有在 surface创建的时候 才有效 ,才构造方法中获取 宽高是获取不到的
width=this.getWidth();
height=this.getHeight();
//初始化绘图线程
gameViewThread=new GameViewThread();
gameViewThread.flag=true;
gameViewThread.start();
}
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
gameViewThread.flag=false; //销毁线程
}
class GameViewThread extends Thread{
public boolean flag;
public void run(){
while(flag){
Canvas canvas=null;
try{
canvas=surfaceHolder.lockCanvas(); //锁定画布 并获取canvas
onDraw(canvas);//调用onDraw 渲染到屏幕
surfaceHolder.unlockCanvasAndPost(canvas); //此步不要忘记了喔 否则界面上显示不出来的
}catch(Exception e){
e.printStackTrace();
}
try {
Thread.sleep(10);//线程休眠时间 控制帧数
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} //每一秒刷新一次
}
}
}
//**************************下面是手势识别的重写方法*******************************************
//屏幕点下
public boolean onDown(MotionEvent arg0) {
Log.d(TAG, "onDown");
Toast.makeText(this.context, "你点击了屏幕", Toast.LENGTH_SHORT).show();
return false;
}
//屏幕点下
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
Log.d(TAG, "onFling");
Toast.makeText(this.context, "你拖动屏幕后弹起", Toast.LENGTH_SHORT).show();
return false;
}
//屏幕点下 并长按时触发
public void onLongPress(MotionEvent e) {
Log.d(TAG, "onLongPress");
Toast.makeText(this.context, "你长按了屏幕", Toast.LENGTH_SHORT).show();
}
//屏幕拖动
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
this.x=this.x-distanceX;
this.y=this.y-distanceY;
Toast.makeText(this.context, "你拖动了屏幕", Toast.LENGTH_SHORT).show();
return false;
}
//屏幕长按
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub
Toast.makeText(this.context, "你长按屏幕后弹起", Toast.LENGTH_SHORT).show();
Log.d(TAG, "onShowPress");
}
//屏幕点击后弹起
public boolean onSingleTapUp(MotionEvent e) {
Log.d(TAG, "onSingleTapUp");
Toast.makeText(this.context, "你弹起屏幕", Toast.LENGTH_SHORT).show();
return false;
}
}
有一点大家需要注意一下 每次执行手势时 可以会执行多个手势通知 大家需要留意一下喔,避免重复操作app逻辑
上面的代码中 红色部分标示了 手势识别的主要部分 大家赶快加到自己的app 里面吧 让自己的app 更有吸引力 其他两种种方式 和这种很类似,各位童鞋可以自己试试喔
在后续的过程中 我们会有一章 游戏地图 介绍 的章节 , 那时我们使用手势识别来拖动地图
欢迎各位童鞋 来拍砖喔,,有啥不懂的地方留言给我喔 一起学习 共同进步 加油 。。
下面是源码地址
http://download.csdn.net/detail/ma_haile/4221223
现在我们来分析下GestureDetector这个类的概括情况
2:在View中的onTouchEvent方法中调用GestureDetector对象中的onTouchEvent方法当事件发生的时候就可以回调该方法