文档章节

Android 手势(Gesture)

让代码飞一会
 让代码飞一会
发布于 2015/07/13 00:56
字数 1592
阅读 852
收藏 29

一、什么是手势?

所谓手势,其实就是指用户手指或触摸笔在触摸屏上的连续触碰行为,比如在屏幕上葱左至右划出一个动作,就是手势,再比如在屏幕上画一个圆圈也是一个手势,手势这种连续的触碰会形成某个方向上的移动趋势,也会形成一个不规则的几何图形。Android对两种手势行为都提供了支持:

1、对于第一种手势行为而言,Android提供了手势检测,并为手势检测提供了相应的监听器。

2、对于第二种手势行为,Android允许开发者添加手势,并提供了相应的API识别用户手势


二、手势检测

Android为手势检测提供了一个GestureDetector类,GestureDetector实例代表了一个手势检测器,创建GestureDetector时需要传入一个GestureDetector.OnGestureListener监听器,负责对用户的手势行为提供响应。

GestureListener包含的事件处理方法如下:

boolean onDown(MotionEvent e):当触碰事件按下时触发该方法。

boolean onFling(MotionEvent e1,MotionEvent e2,float velocityX,float velocityY):当用户在触摸屏上"拖过"时触发该方法。其中velocityX,velocityY代表"拖过"动作在横向、纵向上的速度。

abstract void onLongPress(MotionEvent e):当用户在屏幕上长按时出发该方法。

boolean onScroll(MotionEvent e1,MotionEvent e2,float distanceX,float distanceY):当用户在屏幕上"滚动"时触发该方法。

void onShowPress(MotionEvent e):当用户在触摸屏上按下、并且还为移动和松开时触发该方法。

boolean onSingleTapUp(MotionEvent e):用户在触摸屏上的轻击事件将会出发该方法

以下代码演示了,在什么条件下触发什么手势,触发顺序

public class MainActivity extends Activity implements GestureDetector.OnGestureListener{

   private static final String TAG="TAG";
   private
GestureDetector detector;

   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       
setContentView(R.layout.activity_main);
       
detector = new GestureDetector(this,this);
   
}

   /**
    * 添加手势
    *
@param event
   
* @return
   
*/
   
@Override
   
public boolean onTouchEvent(MotionEvent event) {
       return detector.onTouchEvent(event);
   
}

   /**
    * 按下时
    *
@param e
   
* @return
   
*/
   
@Override
   
public boolean onDown(MotionEvent e) {
       Log.i(TAG,"detector onDown");
       return false;
   
}
   /**
    * 按下未移动时
    *
@param e
   
*/
   
@Override
   
public void onShowPress(MotionEvent e) {
       Log.i(TAG,"detector onShowPress");
   
}
   /**
    * 轻击事件
    *
@param e
   
* @return
   
*/
   
@Override
   
public boolean onSingleTapUp(MotionEvent e) {
       Log.i(TAG,"detector onSingleTapUp");
       return false;
   
}
   /**
    * 滚动时
    *
@param e1
   
* @param e2
   
* @param distanceX
   
* @param distanceY
   
* @return
   
*/
   
@Override
   
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
       Log.i(TAG,"detector onScroll");
       return false;
   
}
   /**
    * 长按时
    *
@param e
   
*/
   
@Override
   
public void onLongPress(MotionEvent e) {
       Log.i(TAG,"detector onLongPress");
   
}
   /**
    * 快速滑动时
    *
@param e1
   
* @param e2
   
* @param velocityX
   
* @param velocityY
   
* @return
   
*/
   
@Override
   
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
       Log.i(TAG,"detector onFling");
       return false;
   
}
}

下面是通过Fling方法进行的一个滑动监听仿的类似ViewPager

public class MainActivity3 extends Activity implements GestureDetector.OnGestureListener{

   private static final String TAG="TAG";
   private
GestureDetector detector;
   private
ViewFlipper mFlipper;
   private
Animation[] animations = new Animation[4];

   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       
setContentView(R.layout.activity_gesture);
       
detector = new GestureDetector(this,this);
       
mFlipper = (ViewFlipper) findViewById(R.id.flipper);
       
mFlipper.addView(addImageView(R.mipmap.image));
       
mFlipper.addView(addImageView(R.mipmap.image2));
       
mFlipper.addView(addImageView(R.mipmap.image3));
       
mFlipper.addView(addImageView(R.mipmap.image4));

       
animations[0] = AnimationUtils.loadAnimation(this,R.anim.left_in);
       
animations[1] = AnimationUtils.loadAnimation(this,R.anim.left_out);
       
animations[2] = AnimationUtils.loadAnimation(this,R.anim.right_in);
       
animations[3] = AnimationUtils.loadAnimation(this,R.anim.right_out);
   
}

   private ImageView addImageView(int resId){
       ImageView imageView = new ImageView(this);
       
imageView.setImageResource(resId);
       
imageView.setScaleType(ImageView.ScaleType.CENTER);
       return
imageView;
   
}

   /**
    * 添加手势
    *
@param event
   
* @return
   
*/
   
@Override
   
public boolean onTouchEvent(MotionEvent event) {
       return detector.onTouchEvent(event);
   
}

   /**
    * 按下时
    *
@param e
   
* @return
   
*/
   
@Override
   
public boolean onDown(MotionEvent e) {
       Log.i(TAG,"detector onDown");
       return false;
   
}
   /**
    * 按下未移动时
    *
@param e
   
*/
   
@Override
   
public void onShowPress(MotionEvent e) {
       Log.i(TAG,"detector onShowPress");
   
}
   /**
    * 轻击事件
    *
@param e
   
* @return
   
*/
   
@Override
   
public boolean onSingleTapUp(MotionEvent e) {
       Log.i(TAG,"detector onSingleTapUp");
       return false;
   
}
   /**
    * 滚动时
    *
@param e1
   
* @param e2
   
* @param distanceX
   
* @param distanceY
   
* @return
   
*/
   
@Override
   
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
       Log.i(TAG,"detector onScroll");
       return false;
   
}
   /**
    * 长按时
    *
@param e
   
*/
   
@Override
   
public void onLongPress(MotionEvent e) {
       Log.i(TAG,"detector onLongPress");
   
}


   private final int FLIP_DISTANCE = 50;
   
/**
    * 快速滑动时
    *
@param e1
   
* @param e2
   
* @param velocityX
   
* @param velocityY
   
* @return
   
*/
   
@Override
   
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
       Log.i(TAG, "detector onFling");

       if
(e1.getX()-e2.getX()>FLIP_DISTANCE){
           mFlipper.setInAnimation(animations[2]);
           
mFlipper.setOutAnimation(animations[1]);
           
mFlipper.showNext();
           return true;
       
}else if(e2.getX()-e1.getX()>FLIP_DISTANCE){
           mFlipper.setInAnimation(animations[0]);
           
mFlipper.setOutAnimation(animations[3]);
           
mFlipper.showPrevious();
           return true;
       
}
       return false;
   
}

三、手势识别库

Android 手势除了提供手势检测之外,还允许应用程序吧用户手势(多个持续的触摸事件在屏幕种形成特定的形状)添加到指定文件夹中,以备以后使用——如果程序需要,当用户下次画出该手势时,系统可识别该手势。

Android使用GestureLibrary来代表手势哭,并提供了GestureLibraries工具类来创建手势库,GestureLibraries提供了如下4个静态方法从不同位置加载手势库。

static GestureLibrary fromFile(String path):

static GestureLibrary fromFile(File path):

static GestureLibrary fromPrivateResource(Context context,int resourceID):从资源库中加载手势

当用户获取GestureLibrary 对象之后,该对象提供来如下方法来添加手势、识别手势。

void addGesture(String entryName,Gesture gesture):添加一个名为entryName的手势。

Set<String> getGestrueEntries():获取该手势哭肿的所有手势名称。

ArrayList<Gesture> getGestures(String entryName):获取entryName名称对应的全部手势。

ArrayList<Prediction> recognize(Gesture gesture):从当前手势库中识别与gesture匹配的全部手势。

————Prediction:name属性表示匹配手势名

————Prediction:score属性表示了手势相似度

void removeEntry(String entryName):删除手势库中识别的entryName对应的手势

void removeGesture(String entryName,Gesture gestrue):删除手势库中entryName、gesture对应的手势

boolean save():当手势库中添加手势或从删除手势后调用改方法来保存手势库


手势绘制与比对

Android 提供了一个手势编辑组件:GestureOverlayView,该组件就像一个"绘图组件",只是用户绘制的是手势,不是图形。

为了监听GestureOverlayView Android提供了OnGestureListener、OnGesturePerformedListener、OnGesturingListener三个监听器,分别用于监听手势事件的开始、结束、完成、取消等事件,一般最常用多是OnGesturePerformedListener,用于提供完成时响应


public class MainActivity4 extends Activity{

   private GestureOverlayView mOverlay;
   private
ImageView mShowGesture;

   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);

       
setContentView(R.layout.activity_gesture2);
       
//获取绘制手势组件
       
mOverlay = (GestureOverlayView) findViewById(R.id.gesture_overlay);
       
//获取绘制后显示组件
       
mShowGesture = (ImageView) findViewById(R.id.show_gesture);

       
//添加绘制后监听
       
mOverlay.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() {
           @Override
           
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {

               //将手势转换为图片
               
Bitmap bitmap = gesture.toBitmap(128, 128, 10, 0xffff0000);
               
mShowGesture.setImageBitmap(bitmap);

               
//获取手势库
               
GestureLibrary gestureLibrary = GestureLibraries.fromFile("/mnt/sdcard/gestures");
               
//判断手势库是否加载
               
if (gestureLibrary.load()) {
                   Toast.makeText(MainActivity4.this, "手势文件已经装载", Toast.LENGTH_SHORT).show();
               
}else{
                   Toast.makeText(MainActivity4.this, "手势文件装载失败", Toast.LENGTH_SHORT).show();
               
}
               //获取所有相似的手势
               
ArrayList<Prediction> recognizes = gestureLibrary.recognize(gesture);
               
Toast.makeText(MainActivity4.this, "手势数量:" + recognizes.size(), Toast.LENGTH_SHORT).show();
               
//遍历相似的手势,相似度高于5的才打印
               
for (Prediction recognize : recognizes) {
                   if (recognize.score > 5.0) {
                       Toast.makeText(MainActivity4.this, "手势名称:" + recognize.name + " 相似度:" + recognize.score, Toast.LENGTH_SHORT).show();
                   
}
               }
               //添加手势 (手势名称,手势)
               
gestureLibrary.addGesture("gesture", gesture);
               
//保存手势
               
gestureLibrary.save();
           
}
       });

   
}


}

本文转载自:

让代码飞一会
粉丝 171
博文 36
码字总数 3406
作品 0
海淀
项目经理
私信 提问
加载中

评论(1)

张林思密达
张林思密达
教主万福,单元测试是个什么东东。。。工作时候用的多吗,面试问到咋说啊。。
Android 3.0 具体支持哪些Gesture?

Android 3.0 具体支持哪些Gesture? 没中手势,具体是如何定义的? 从platform level, 该如何测试这些Gesture? 谢谢了 Android 新人, 诚请回复!...

tang4636
2011/06/09
382
0
【Android游戏开发十七】让玩家自定义手势玩转Android游戏!—Android Gesture之【输入法手势技术】

李华明Himi 原创,转载务必在明显处注明: 转载自【黑米GameDev街区】 原文链接: http://www.himigame.com/android-game/340.html 很多童鞋说我的代码运行后,点击home或者back后会程序异常,...

迷途d书童
2012/03/19
310
0
编写 Android 触摸屏手势识别程序

很多时候,利用触摸屏的Fling、Scroll等Gesture(手势)操作来操作会使得应用程序的用户体验大大提升,比如用Scroll手势在 浏览器中滚屏,用Fling在阅读器中翻页等。在Android系统中,手势的...

红薯
2009/07/02
36.9K
22
android:onTouch()和onTouchEvent()的区别?看完这篇文章就知道了

Android Touch Screen 与传统Click Touch Screen不同,会有一些手势(Gesture),例如Fling,Scroll等等。这些Gesture会使用户体验大大提升。 Android中的Gesture识别(detector)是通过Gesture...

鉴客
2011/10/08
16.5K
1
[小技巧]Android端Chrome如何启用易于单手操作的历史导航手势

伴随着手机屏幕变得越来越大尤其是全面屏的推进,整体交互也从传统的按钮交互向手势交互。谷歌已经考虑为Android端Chrome浏览器引入更多基于手势的交互,不过在启用之前你需要找到对应的Fla...

稿源:
03/22
0
0

没有更多内容

加载失败,请刷新页面

加载更多

springboot初探---spring-boot-starter-web究竟干了啥

上一篇已经简单介绍了启动类的部分,这一篇主要讨论一下springboot引入的哪些依赖 我们都知道想用springboot做一个web应用,首先要做的是引入相关依赖,两步操作: 1、添加spring-boot-start...

计算机狼
32分钟前
5
0
基于Rocket.chat搭建内网聊天系统(使用docker,本机不需要安装meteor)

您可能不希望使用标准的Docker命令,而是希望对部署进行更多的自动化管理。这就是使用Docker-compose可能会派上用场的地方。 确保您已安装Docker和Docker-compose并且可以正常运行。 docker...

吴伟祥
35分钟前
6
0
conda 更新源

更新conda 源为阿里源 conda config --add channels http://mirrors.aliyun.com/pypi/simple conda config --set show_channel_urls yes 阿里云: http://mirrors.aliyun.com/pypi/simple/ 豆......

Mr_Tea伯奕
35分钟前
4
0
java 泛型使用

每次写泛型方法都翻下百度,还是自己记录下把。 1、定义一个泛型方法,使用传入参数类型来传递泛型。这种用法在封装json序列化工具类应该会用到。 List<xxx> aa = getList(xxx.class);pr...

朝如青丝暮成雪
39分钟前
6
0
深入了解Java模板引擎Freemarker

前言 常用的Java模板引擎包括:JSP、Freemarker、Thymeleaf、Velocity,从Github上查阅到这几款主流的模板引擎的性能的对比,总体上看,JSP、Freemarker、Thymeleaf、Velocity在性能上差别不...

code-ortaerc
40分钟前
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部