Android基础新手教程——3.8 Gesture(手势)

标签(空格分隔): Android基础新手教程


本节引言:

周六不歇息,刚剪完了个大平头回来。继续码字~

好的,本节给大家带来点的是第三章的最后一节——Gesture(手势),

用过魅族手机的朋友相信对手势肯定是不陌生的。在home键两側像屏幕内滑动,

能够打开后台任务列表等等~在应用中通过手势来操作会大大提升用户体验。

比方Scroll手势在浏览器中个滚屏,Fling在浏览器中的换页等!

当然,有利也有弊,比方不当的手势操作引起APP Carsh,经常这样但是会引起用户不满的。

所以是否要为你的应用添加手势,可要考虑清楚哦。另外手势要和前面学的单指/多指触碰相区分哦。

手势是:连续触碰的行为,比方左右上下滑动屏幕,又或者画一些不规则的几何图形!

Android对上述两种手势行为都提供了支持:

  • Android提供手势检測,并为手势识别提供了相应的监听器。
  • Android执行开发人员自行加入手势,而且提供了相应的API识别用户手势!

假设你的手机是Android 4.x的原生Android系统的话。你可能能够在你的手机或者平板上看到谷歌

提供的一个Gesture Builder的APP,该应用同意用户以类似于涂鸦的方式绘制一个手写符号,使之

相应一个字符串名称!当然。没有这种手机也没关系。我们有模拟器嘛,自己开个4.0的系统试试

就知道了,另外,我们能够到\mmt\sdcard\gestures获取到保存手势的文件!

好了,唠唠叨叨那么多,開始讲正题吧!

对了。贴下官方API文档先:GestureDetector


1.Android中手势交互的执行顺序

  • 1.手指触碰屏幕时,触发MotionEvent事件!

  • 2.该事件被OnTouchListener监听,可在它的onTouch()方法中获得该MotionEvent对象。
  • 3.通过GestureDetector转发MotionEvent对象给OnGestureListener
  • 4.我们能够通过OnGestureListener获得该对象,然后获取相关信息。以及做相关处理。

我们来看下上述的三个类都是干嘛的:

MotionEvent: 这个类用于封装手势、触摸笔、轨迹球等等的动作事件。

其内部封装了两个重要的属性X和Y,这两个属性分别用于记录横轴和纵轴的坐标。

GestureDetector: 识别各种手势。

OnGestureListener: 这是一个手势交互的监听接口,当中提供了多个抽象方法,

并依据GestureDetector的手势识别结果调用相相应的方法。

——上述资料摘自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1020/448.html

2.GestureListener具体解释:

从1中我们知道了监听手势的关键是:GestureListener

他给我们提供了下述的回调方法:

  • 按下(onDown): 刚刚手指接触到触摸屏的那一刹那,就是触的那一下。
  • 抛掷(onFling): 手指在触摸屏上迅速移动,并松开的动作。

  • 长按(onLongPress): 手指按在持续一段时间,而且没有松开。
  • 滚动(onScroll): 手指在触摸屏上滑动。

  • 按住(onShowPress): 手指按在触摸屏上,它的时间范围在按下起效。在长按之前。

  • 抬起(onSingleTapUp):手指离开触摸屏的那一刹那。

知道了GestureListener的相关方法后,实现手势检測也非常easy,过程例如以下:

  • Step 1: 创建GestureDetector对象,创建时需实现GestureListener传入
  • Step 2: 将Activity或者特定组件上的TouchEvent的事件交给GestureDetector处理就可以!

    我们写个简单的代码来验证这个流程。即重写相应的方法:

代码例如以下:

public class MainActivity extends AppCompatActivity {

    private MyGestureListener mgListener;
private GestureDetector mDetector;
private final static String TAG = "MyGesture"; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//实例化GestureListener与GestureDetector对象
mgListener = new MyGestureListener();
mDetector = new GestureDetector(this, mgListener); } @Override
public boolean onTouchEvent(MotionEvent event) {
return mDetector.onTouchEvent(event);
} //自己定义一个GestureListener,这个是View类下的。别写错哦!!!
private class MyGestureListener implements GestureDetector.OnGestureListener { @Override
public boolean onDown(MotionEvent motionEvent) {
Log.d(TAG, "onDown:按下");
return false;
} @Override
public void onShowPress(MotionEvent motionEvent) {
Log.d(TAG, "onShowPress:手指按下一段时间,不过还没到长按");
} @Override
public boolean onSingleTapUp(MotionEvent motionEvent) {
Log.d(TAG, "onSingleTapUp:手指离开屏幕的一瞬间");
return false;
} @Override
public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
Log.d(TAG, "onScroll:在触摸屏上滑动");
return false;
} @Override
public void onLongPress(MotionEvent motionEvent) {
Log.d(TAG, "onLongPress:长按而且没有松开");
} @Override
public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
Log.d(TAG, "onFling:迅速滑动,并松开");
return false;
}
} }

相应操作截图:

1.按下后马上松开:

2.长按后松开:

3.轻轻一滑。同一时候松开:

4.按住后不放持续做滑动操作:

PS:从上述结果来看。我们发现了一个问题:

我们实现OnGestureListener须要实现全部的手势。可能我针对的不过滑动,但是你还是要去重载。

这显得非常逗逼。是吧。官方肯定会给出解决方法滴。官方另外给我们提供了一个SimpleOnGestureListener类

只需把上述的OnGestureListener替换成SimpleOnGestureListener就可以!


3.简单的样例:下滑关闭Activity,上滑启动新的Activity

这里就用上述的SimpleOnGestureListener来实现吧:

执行效果图:

实现代码:

public class MainActivity extends AppCompatActivity {

    private GestureDetector mDetector;
private final static int MIN_MOVE = 200; //最小距离
private MyGestureListener mgListener; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//实例化SimpleOnGestureListener与GestureDetector对象
mgListener = new MyGestureListener();
mDetector = new GestureDetector(this, mgListener);
} @Override
public boolean onTouchEvent(MotionEvent event) {
return mDetector.onTouchEvent(event);
} //自己定义一个GestureListener,这个是View类下的。别写错哦!!!
private class MyGestureListener extends GestureDetector.SimpleOnGestureListener { @Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float v, float v1) {
if(e1.getY() - e2.getY() > MIN_MOVE){
startActivity(new Intent(MainActivity.this, MainActivity.class));
Toast.makeText(MainActivity.this, "通过手势启动Activity", Toast.LENGTH_SHORT).show();
}else if(e1.getY() - e2.getY() < MIN_MOVE){
finish();
Toast.makeText(MainActivity.this,"通过手势关闭Activity",Toast.LENGTH_SHORT).show();
}
return true;
}
} }

结果分析:

从上面的对照就能够知道,相比起SimpleOnGestureListener使用SimpleOnGestureListener

显得更加的简单,想重写什么方法就重写什么方法。另外样例比較简单。大家能够自己试试

其它玩法,比方通过手势缩放图片~


4.手势加入与识别:

除了上面解说的手势检測外,Android还执行我们将手势进行加入,然后提供了相关的识别API;

Android中使用GestureLibrary来代表手势库,提供了GestureLibraries工具类来创建手势库。

四个载入手势库的静态方法:

获得GestureLibraries对象后,就能够使用该对象提供的下述方法来做相应操作了:

相关方法:

  • public void addGesture (String entryName, Gesture gesture):加入一个名为entryName的手势
  • public Set getGestureEntries ():获得手势库中全部手势的名称
  • public ArrayList getGestures (String entryName):获得entryName名称相应的全部手势
  • public ArrayList recognize (Gesture gesture): 从当前手势库中识别与gesture匹配的全部手势
  • public void removeEntry (String entryName):删除手势库中entryName名称相应的手势
  • public void removeGesture (String entryName, Gesture gesture):删除手势库中entryName和gesture都匹配的手势
  • public abstract boolean save ():想手势库中加入手势或从中删除手势后调用该方法保存手势库

GestureOverlayView手势编辑组件:

Android为GestureOverlayView提供了三种监听器接口,例如以下。一般经常使用的是:OnGesturePerformedListener;用于手势完毕时提供响应!


5.手势加入演示样例:

PS:样例引用的是——李刚《Android疯狂讲义》的代码

执行效果图:

好吧,以下贴下实现代码:

两个布局文件:activity_main.xml和dialog_save.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity"> <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="请在下方屏幕中绘制手势~"
android:textSize="20sp"/> <!-- gestureStrokeType控制手势是否须要一笔完毕,multiple表示同意多笔-->
<android.gesture.GestureOverlayView
android:id="@+id/gesture"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gestureStrokeType="multiple" /> </LinearLayout>
<?

xml version="1.0" encoding="utf-8"?

>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:text="请填写手势名称:"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/edit_name"/>
</LinearLayout> <ImageView
android:id="@+id/img_show"
android:layout_width="128dp"
android:layout_height="128dp"
android:layout_marginTop="10dp"/> </LinearLayout>

MainActivity.java:

public class MainActivity extends AppCompatActivity {

    private EditText editText;
private GestureOverlayView gesture; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取手势编辑组件后,设置相关參数
gesture = (GestureOverlayView) findViewById(R.id.gesture);
gesture.setGestureColor(Color.GREEN);
gesture.setGestureStrokeWidth(5);
gesture.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() {
@Override
public void onGesturePerformed(GestureOverlayView gestureOverlayView, final Gesture gesture) {
View saveDialog = getLayoutInflater().inflate(R.layout.dialog_save,null,false);
ImageView img_show = (ImageView) saveDialog.findViewById(R.id.img_show);
final EditText edit_name = (EditText) saveDialog.findViewById(R.id.edit_name);
Bitmap bitmap = gesture.toBitmap(128,128,10,0xffff0000);
img_show.setImageBitmap(bitmap);
new AlertDialog.Builder(MainActivity.this).setView(saveDialog)
.setPositiveButton("保存",new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialogInterface, int i) {
//获取文件相应的手势库
GestureLibrary gestureLib = GestureLibraries.fromFile("/mnt/sdcard/mygestures");
gestureLib.addGesture(edit_name.getText().toString(),gesture);
gestureLib.save();
}
}).setNegativeButton("取消", null).show();
}
});
}
}

最后还须要在AndroidManifest.xml中加入写入SD卡的权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

6.手势识别演示样例:

实现代码:

public class MainActivity extends AppCompatActivity {

    private GestureOverlayView gesture;
private GestureLibrary gestureLibrary;
private Context mContext; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = MainActivity.this;
gestureLibrary = GestureLibraries.fromFile("mmt/sdcard/mygestures");
if (gestureLibrary.load()) {
Toast.makeText(mContext, "手势库载入成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(mContext, "手势库载入失败", Toast.LENGTH_SHORT).show();
} //获取手势编辑组件后,设置相关參数
gesture = (GestureOverlayView) findViewById(R.id.gesture);
gesture.setGestureColor(Color.GREEN);
gesture.setGestureStrokeWidth(5);
gesture.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() {
@Override
public void onGesturePerformed(GestureOverlayView gestureOverlayView, final Gesture gesture) {
//识别用户刚绘制的手势
ArrayList<Prediction> predictions = gestureLibrary.recognize(gesture);
ArrayList<String> result = new ArrayList<String>();
//遍历全部找到的Prediction对象
for (Prediction pred : predictions) {
if (pred.score > 2.0) {
result.add("与手势【" + pred.name + "】类似度为" + pred.score);
}
}
if (result.size() > 0) {
ArrayAdapter<Object> adapter = new ArrayAdapter<Object>(mContext,
android.R.layout.simple_dropdown_item_1line, result.toArray());
new AlertDialog.Builder(mContext).setAdapter(adapter,null).setPositiveButton("确定",null).show();
}else{
Toast.makeText(mContext,"无法找到匹配的手势!",Toast.LENGTH_SHORT).show();
}
}
});
}
}

另外别忘了在AndroidManifest.xml文件里加入读SD卡的权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

本节小结:

好的,本节介绍了Android中的Gesture手势,解说了手势推断。手势加入。手势识别三个内容

,大部分样例来自于李刚老师的Android疯狂讲义,有兴趣的能够看看该书~谢谢

Android基础新手教程——3.8 Gestures(手势)的更多相关文章

  1. Android基础新手教程——3.4 TouchListener PK OnTouchEvent + 多点触碰

    Android基础新手教程--3.4 TouchListener PK OnTouchEvent + 多点触碰 标签(空格分隔): Android基础新手教程 本节引言: 如题,本节给大家带来的是To ...

  2. Android基础新手教程——1.10 反编译APK获代替码&amp;资源

    Android基础新手教程--1.10 反编译APK获代替码&资源 标签(空格分隔): Android基础新手教程 本节引言: "反编译Apk".看上去好像好像非常高端的样 ...

  3. Android基础新手教程——1.6 .9(九妹)图片怎么玩

    Android基础新手教程--1.6 .9(九妹)图片怎么玩 标签(空格分隔): Android基础新手教程 1.本节引言: 可能有的一些疑问: 1.什么是.9图片? 答:图片后缀名前有.9的图片,如 ...

  4. Android基础新手教程——3.1 基于监听的事件处理机制

    Android基础新手教程--3.1.1 基于监听的事件处理机制 标签(空格分隔): Android基础新手教程 本节引言: 第二章我们学习的是Android的UI控件,我们能够利用这些控件构成一个精 ...

  5. Android基础新手教程——4.1.3 Activity登堂入室

    Android基础新手教程--4.1.3 Activity登堂入室 标签(空格分隔): Android基础新手教程 本节引言: 好的,在学习了两节的Activity后相信大家已经知道怎样去使用Acti ...

  6. Android基础新手教程——4.1.2 Activity初窥门径

    Android基础新手教程--4.1.2 Activity初窥门径 标签(空格分隔): Android基础新手教程 本节引言: 上一节中我们对Activity一些主要的概念进行了了解,什么是Activ ...

  7. Android基础新手教程——4.4.1 ContentProvider初探

    Android基础新手教程--4.4.1 ContentProvider初探 标签(空格分隔): Android基础新手教程 本节引言: 本节给大家带来的是Android四大组件中的最后一个--Con ...

  8. Android基础新手教程——3.7 AnsyncTask异步任务

    Android基础新手教程--3.7 AnsyncTask异步任务 标签(空格分隔): Android基础新手教程 本节引言: 本节给大家带来的是Android给我们提供的一个轻量级的用于处理异步任务 ...

  9. Android基础新手教程——4.3.1 BroadcastReceiver牛刀小试

    Android基础新手教程--4.3.1 BroadcastReceiver牛刀小试 标签(空格分隔): Android基础新手教程 本节引言 本节我们将来学习Android四大组件中的第三个:Bro ...

随机推荐

  1. HTML学习----------DAY1 第三节

    本章通过实例向您演示最常用的 HTML 标签. 提示:不要担心本章中您还没有学过的例子,您将在下面的章节中学到它们. 提示:学习 HTML 最好的方式就是边学边做实验.我们为您准备了很好的 HTML ...

  2. Codeforces Round #313 (Div. 2) 解题报告

    A. Currency System in Geraldion: 题意:有n中不同面额的纸币,问用这些纸币所不能加和到的值的最小值. 思路:显然假设这些纸币的最小钱为1的话,它就能够组成随意面额. 假 ...

  3. 关于post请求“CAUTION: Provisional headers are shown”【转】

    在POST请求中偶尔会出现"CAUTION: Provisional headers are shown" 这个警告的意思是说:请求的资源可能会被(扩展/或其它什么机制)屏蔽掉. ...

  4. JVM-java字符编码

    在JVM内部,所有的字符都是用Unicode编码的.而对于JVM所在操作系统的文件系统,可能有不同的编码类型. 由于JVM和OS文件系统所使用的编码方式不同,JVM在与操作系统进行数据交互的时候,就会 ...

  5. jQuery插件开发初探

    最简单的插件 $.fn.changeStyle = function (colorStr) { $(this).css('color',colorStr); } 应用如下: <!DOCTYPE ...

  6. Centos7 ssh免密码登陆

    摘要:安装openssl openssl-devel 不过有些centos自带 192.168.161.5  192.168.161.15 本版本用centos7 (192.168.161.5) yu ...

  7. 利用cvFindExtrinsicCameraParams2求取相机外参数

    cvFindExtrinsicCameraParams2函数的定义: void cvFindExtrinsicCameraParams2( const CvMat* object_points, co ...

  8. JAVA使用Gson解析json数据,实例

    封装类Attribute: public class Attribute { private int id; private String name; private int age; public ...

  9. 学习思考:思考>努力

    学.习.思.考 学习.思考,这2个词,4个字,其实代表了4个不同的动作:学.习.思.考. 学,就是从外部(他人)获得. 习,就是练习,行动. 思,就是从内部(自己)获得. 考,就是考量,检测. 因此, ...

  10. vue.js原生组件化开发(二)——父子组件

    前言 在了解父子组件之前应先掌握组件开发基础.在实际开发过程中,组件之间可以嵌套,也因此生成父子组件. 父子组件创建流程 1.构建父子组件 1.1 全局注册 (1)构建注册子组件 //构建子组件chi ...