本系列文章均为A2BGeek原创,转载务必在明显处注明:
转载自A2BGeek的【Android每周专题】系列,原文链接:http://blog.csdn.net/benbmw2008/article/details/11367631

这篇专题来研究一下Android的触摸屏手势Gesture,Android的手势有两种,一种是View和Activity的(基于触摸屏事件,所以Activity也能添加手势),一种是手写输入法或者一些手机浏览器的快捷手势那样的带笔迹的手势识别。这一点从API文档中就能体现出来:分别有android.view.GestureDetector和android.gesture.Gesture。

我们先来介绍View和Activity的手势,再介绍输入法手势识别。

View和Activity的手势

这一部分想必大家都已经非常熟悉了,现在很多APP都会加入手势来提高交互体验,其中在某个界面向右Fling关闭该界面这一操作貌似成了APP的标配了。废话不多说了,直接进入正题。
为View和Activity加入手势操作的步骤如下:
1、为View或者Activity实现OnGestureListener接口。
2、覆写View或者Activity的OnTouchEvent方法,这里要返回GestureDetector.onTouchEvent()。
3、覆写你需要的手势的回调方法。
这里解释一下各种回调方法的含义:
按下(onDown): 刚刚手指接触到触摸屏的那一刹那,就是触的那一下。
抛掷(onFling): 手指在触摸屏上迅速移动,并松开的动作。
长按(onLongPress): 手指按在持续一段时间,并且没有松开。
滚动(onScroll): 手指在触摸屏上滑动。
按住(onShowPress): 手指按在触摸屏上,它的时间范围在按下起效,在长按之前。
抬起(onSingleTapUp):手指离开触摸屏的那一刹那。
除了这些定义之外,鄙人也总结了一点算是经验的经验吧,在这里和大家分享一下。
任何手势动作都会先执行一次按下(onDown)动作。
长按(onLongPress)动作前一定会执行一次按住(onShowPress)动作。
按住(onShowPress)动作和按下(onDown)动作之后都会执行一次抬起(onSingleTapUp)动作。
长按(onLongPress)、滚动(onScroll)和抛掷(onFling)动作之后都不会执行抬起(onSingleTapUp)动作。
我这里贴上一段代码,大家可以看一下实现的步骤,实验代码和触摸屏事件专题的代码差不多,我就不重复上传了。
package com.example.gesturedemo;import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.widget.TextView;public class MyTextView extends TextView implements OnGestureListener {private GestureDetector mGestureDetector;public MyTextView(Context context) {super(context);// TODO Auto-generated constructor stubmGestureDetector = new GestureDetector(context, this);}public MyTextView(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stubmGestureDetector = new GestureDetector(context, this);}public MyTextView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);// TODO Auto-generated constructor stubmGestureDetector = new GestureDetector(context, this);}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {// TODO Auto-generated method stubDebugTool.log("MyTextView--->dispatchTouchEvent");return super.dispatchTouchEvent(event);}@Overridepublic boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubDebugTool.log("MyTextView--->onTouchEvent");// int action = event.getAction();// switch (action) {// case MotionEvent.ACTION_DOWN:// DebugTool.log("MyTextView--->onTouchEvent--->DOWN");// break;// case MotionEvent.ACTION_MOVE:// DebugTool.log("MyTextView--->onTouchEvent--->MOVE");// break;// case MotionEvent.ACTION_UP:// DebugTool.log("MyTextView--->onTouchEvent--->UP");// break;// }return mGestureDetector.onTouchEvent(event);}@Overridepublic boolean onDown(MotionEvent e) {// TODO Auto-generated method stubreturn false;}@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {// TODO Auto-generated method stubDebugTool.log("MyTextView--->onFling");return false;}@Overridepublic void onLongPress(MotionEvent e) {// TODO Auto-generated method stub}@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,float distanceY) {// TODO Auto-generated method stubreturn false;}@Overridepublic void onShowPress(MotionEvent e) {// TODO Auto-generated method stub}@Overridepublic boolean onSingleTapUp(MotionEvent e) {// TODO Auto-generated method stubreturn false;}}

在OnGestureListener的带返回值的几个回调方法默认返回false的情况下,你会发现Fling手势是识别不到的,这是什么原因呢?这需要用上一专题的知识来解释 http://blog.csdn.net/benbmw2008/article/details/11143893。 大家应该能看出来手势是基于触摸屏事件传递的,对照着上一篇的“默认事件流向”图,读者可以想象其实就是在“MyTextView onTouchEvent”和“MyRelativeLayout onTouchEvent”之间加一个"MyTextView's GestureDetector onTouchEvent",而"MyTextView's GestureDetector onTouchEvent"返回false,事件还是会继续传递给“MyRelativeLayout onTouchEvent”。解决的办法是什么呢?自然是把OnGestureListener的带返回值的几个回调方法返回true,这样触摸屏事件就被“GestureDetector onTouchEvent”所消费,看一下日志会更加清楚:

09-08 10:36:10.714: V/gesturedemo(13130): MainActivity--->dispatchTouchEvent
09-08 10:36:10.718: V/gesturedemo(13130): MyRelativeLayout--->dispatchTouchEvent
09-08 10:36:10.722: V/gesturedemo(13130): MyRelativeLayout--->onInterceptTouchEvent
09-08 10:36:10.722: V/gesturedemo(13130): MyTextView--->dispatchTouchEvent
09-08 10:36:10.722: V/gesturedemo(13130): MyTextView--->onTouchEvent
09-08 10:36:10.824: V/gesturedemo(13130): MainActivity--->dispatchTouchEvent
09-08 10:36:10.828: V/gesturedemo(13130): MyRelativeLayout--->dispatchTouchEvent
09-08 10:36:10.832: V/gesturedemo(13130): MyRelativeLayout--->onInterceptTouchEvent
09-08 10:36:10.835: V/gesturedemo(13130): MyTextView--->dispatchTouchEvent
09-08 10:36:10.835: V/gesturedemo(13130): MyTextView--->onTouchEvent
09-08 10:36:10.863: V/gesturedemo(13130): MainActivity--->dispatchTouchEvent
09-08 10:36:10.878: V/gesturedemo(13130): MyRelativeLayout--->dispatchTouchEvent
09-08 10:36:10.886: V/gesturedemo(13130): MyRelativeLayout--->onInterceptTouchEvent
09-08 10:36:10.886: V/gesturedemo(13130): MyTextView--->dispatchTouchEvent
09-08 10:36:10.886: V/gesturedemo(13130): MyTextView--->onTouchEvent
09-08 10:36:10.898: V/gesturedemo(13130): MainActivity--->dispatchTouchEvent
09-08 10:36:10.898: V/gesturedemo(13130): MyRelativeLayout--->dispatchTouchEvent
09-08 10:36:10.898: V/gesturedemo(13130): MyRelativeLayout--->onInterceptTouchEvent
09-08 10:36:10.898: V/gesturedemo(13130): MyTextView--->dispatchTouchEvent
09-08 10:36:10.898: V/gesturedemo(13130): MyTextView--->onTouchEvent
09-08 10:36:10.917: V/gesturedemo(13130): MainActivity--->dispatchTouchEvent
09-08 10:36:10.917: V/gesturedemo(13130): MyRelativeLayout--->dispatchTouchEvent
09-08 10:36:10.917: V/gesturedemo(13130): MyRelativeLayout--->onInterceptTouchEvent
09-08 10:36:10.917: V/gesturedemo(13130): MyTextView--->dispatchTouchEvent
09-08 10:36:10.917: V/gesturedemo(13130): MyTextView--->onTouchEvent
09-08 10:36:10.917: V/gesturedemo(13130): MyTextView--->onFling
Activity的手势实现和View的是一样的,这里就不重复说了,只不过你不用再修改手势回调方法的返回值了。
下面我又突然想到了一个问题,就是手势区域重复了怎么办?举个例子,有一个只包含一个View的Activity,需要实现在View区域向右Fling关闭Activity,向下Fling做别的一些操作,
1、如果逻辑都实现在View上是非常简单的,在onFling中直接判断就可以了。
2、但是有的情况只允许向右Fling的判断实现在Activity中,向下Fling的判断实现在View中(或者相反,总之是分开判断),这个时候又该怎么办?
对于第二种情况,答案还是很有意思的,读者如果感兴趣的话可以发表评论,有营养的评论超过5条后我会将答案的代码下载地址放在文章的最后。

输入法手势识别

在手写输入中,会为每一个字符定义一个特征码,这些特征码都保存在相应的文件中(可能有一个或多个这样的文件),当用户绘制一个描述字符的图形时,系统会为所绘制的图形提取特征码,然后会在保存特征码文件中查找相对应的特征码,如果找到,就会将对应的字符返回。其中,这些文件被称为手势文件。
我们来做一个简单的手势识别APP。
一、首先需要建立手势文件,这里需要借助SDK自带的Sample,大家在Eclipse中File--->New--->Project--->Android--->Android Sample Project,选择GestureBuilder,运行之,建立几个自己的手势,然后把手势文件拿出来即可(每建立一个手势会有一个Toast弹出,告诉你文件的保存路径)。
其实可以想像gestures手势文件中就是一个一个的键值对。
二、把gestures文件放入工程的res/raw目录下,有关raw和assets的区别,请移步 http://blog.csdn.net/benbmw2008/article/details/8754373。
布局文件如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent" ><TextViewandroid:id="@+id/tv1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerHorizontal="true"android:text="@string/hello_world"android:textSize="24sp" /><android.gesture.GestureOverlayViewandroid:id="@+id/gestures"android:layout_width="200dip"android:layout_height="200dip"android:layout_centerInParent="true"android:background="#33B5E5" ></android.gesture.GestureOverlayView></RelativeLayout>

代码如下:

package com.a2bgeek.gesturedemo2;import java.util.ArrayList;import android.os.Bundle;
import android.app.Activity;
import android.gesture.Gesture;
import android.gesture.GestureLibraries;
import android.gesture.GestureLibrary;
import android.gesture.GestureOverlayView;
import android.gesture.GestureOverlayView.OnGesturePerformedListener;
import android.gesture.Prediction;
import android.view.Menu;
import android.widget.TextView;
import android.widget.Toast;public class MainActivity extends Activity {private TextView mTextView;private GestureOverlayView mGestureOverlayView;private GestureLibrary mGestureLibrary;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initViews();}private void initViews() {mTextView = (TextView) findViewById(R.id.tv1);mGestureLibrary = GestureLibraries.fromRawResource(getApplicationContext(), R.raw.gestures);if (mGestureLibrary.load()) {mGestureOverlayView = (GestureOverlayView) findViewById(R.id.gestures);mGestureOverlayView.addOnGesturePerformedListener(new MyGesturePerformListener());}}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}private class MyGesturePerformListener implementsOnGesturePerformedListener {@Overridepublic void onGesturePerformed(GestureOverlayView overlay,Gesture gesture) {// TODO Auto-generated method stubArrayList<Prediction> list = mGestureLibrary.recognize(gesture);if (list.size() > 0) {//list是mGestureLibrary中可能与gesture匹配的手势集,匹配的程度会有一个score评分。StringBuilder sb = new StringBuilder();for (Prediction prediction : list) {sb.append(prediction.name);sb.append(":");sb.append(prediction.score);sb.append("\n");}mTextView.setText(sb.toString());} else {Toast.makeText(getApplicationContext(), "没有匹配",Toast.LENGTH_SHORT).show();}}}}

好了,今天的内容就到这里了,第一周更新了两篇专题,是个良好的开始,嗯嗯,加油。
实验代码点击下载

近期准备更新一篇 快递查询的应用制作,用到了快递100的接口。

【Android每周专题】触摸屏手势相关推荐

  1. Android OpenGL射线拾取手势旋转(二)

    上回分解-_-!,Android OpenGL射线拾取&手势旋转(一). 3)Renderer:RayPickRenderer.java OpenGL渲染器,比较多的东西都在这里面了. pub ...

  2. BAT Android面试专题深入探究:四大组件+ViewPager+组件化架构+Bitmap

    本篇是结合我之前面试别人的经验,以及跟一些在BAT上班的朋友,讨论总结出的一份很深的大公司需要用到的一些高端Android技术.这里也专门整理了一个文档,重点和难点都有详细解析.这些题目有点技术含量, ...

  3. Android系统(111)---Android稳定性专题之开篇

    Android稳定性专题之开篇 一.稳定性问题有哪些 Android应用程序自身的稳定性问题主要有两类一类是Crash,一类是ANR. Crash:比如空指针.数组越界.子线程中刷新UI等错误造成的程 ...

  4. android 电池续航时间,《Android优化专题》——优化电池续航能力

    <Android优化专题>--优化电池续航能力 一.监测设备的电量和充电状态 在用户充电时,程序做任何操作都不会太受到电量影响,此时就适合做一些下载,刷新数据等耗电操作. 1. 判断当前充 ...

  5. android自定义手势,Android编程实现自定义手势的方法详解

    本文实例讲述了Android编程实现自定义手势的方法.分享给大家供大家参考,具体如下: 之前介绍过如何在Android程序中使用手势,主要是系统默认提供的几个手势,这次介绍一下如何自定义手势,以及如何 ...

  6. Android Things专题 1.前世今生

    文| 谷歌开发者技术专家, 物联网方向 (IOT GDE) 王玉成(York Wang) 2016 年 12 月,Google 发布了 Developer Preview 版的 Android Thi ...

  7. Unity实现触摸屏手势控制镜头旋转与缩放

    一.关于 Unity实现触摸屏手势控制镜头旋转与缩放脚本 /*** * Title:"三维可视化" 项目 * 主题:手势控制物体的旋转缩放 * Description: * 功能: ...

  8. android 按钮手势,如何在Android 10中使用手势导航或如何关闭它

    谷歌移动操作系统的最新版本Android 10带有许多出色的新功能.在Android 9.0 Pie中向Android中引入了手势导航 - 它使用滑动和其他操作来控制手机,而不是点击按钮.在Andro ...

  9. Android面试专题系列(四):Activity之间如何进行通信→LiveDataBus

    不诗意的女程序媛不是好厨师~ 转载请注明出处,From李诗雨-https://blog.csdn.net/cjm2484836553/article/details/105147592 <And ...

最新文章

  1. android jni语法,Android NDK中的JNIEXPORT和JNICALL
  2. 阅读Book:MultiObjective using Evolutionary Algorithms(7)---Weighted Sum Methods ε-Constraint Methods
  3. 机器就能绘制这样的作品,你还去写生吗?(续)
  4. NHibernate之Mapping 之 Property
  5. vscode创建工作区_区领导调研工业区高楼村乡村振兴示范村创建工作!
  6. mybaits二十七:spring, spring mvc,mybatis(ssm) 整合
  7. Di-visible Confusion 贪心,模拟,思维,时间复杂度
  8. c语言字符串匹配函数index,C语言(函数)学习之index、rindex
  9. 最全Spring Boot2.x系列Config配置集成篇-1参数配置
  10. https 443 怎么改成80_阿里云购买免费https证书并用nginx配置代理详解(2020年9月)...
  11. 关于View的Animation无法停止问题
  12. 你的跨境电商独立站访问性能如何?
  13. 在VMware workstation 9.0中安装Windows server 2012 和 Hyper-v(虚拟机中安装虚拟机)
  14. springmvc线程安全问题
  15. 快速备份sqlserver2005以上版本数据库的方法-摘自网络
  16. Spring Boot 2.4.0-RC1, 2.1.18, 2.2.11 和 2.3.5 发布
  17. 《跑步人生》 作者:村上春树
  18. 修改IP的cmd命令
  19. python换照片底色_详解Python给照片换底色(蓝底换红底)
  20. 思绪,飘在青山绿水间

热门文章

  1. CLIP Learning Transferable Visual Models From Natural Language Supervision (文本和图像的对比学习)--文献翻译和笔记
  2. 如果写不出好的和弦就在洒满阳光的钢琴前一起吃布丁+与8有关的事儿
  3. 西游记笔记与想法(3)
  4. 嵌入式设备的JTAG,Angle,和ICE三种调试笔记
  5. idea 双击打不开了咋办
  6. 企业完成云转型的成功之道:云成本优化管理
  7. RTK和RTD有什么区别
  8. mmdetection安装教程 | 踩坑总结
  9. 伦茨科技-智能语音遥控器
  10. 宽带运行商服务器,家用宽带200兆,300兆,500兆与1000兆有什么区别吗?