Android的手势操作(Gesture)
上一篇介绍的onTouch提供的事件还是相对较简单,如果需要处理一些复杂的手势,用这个接口就会很麻烦,因为我们要根据用户触摸的轨迹去判断是什么手势。幸好Android SDK给我们提供了GestureDetector类,通过这个类我们可以识别很多的手势,主要是通过他的onTouchEvent(event)方法完成了不同手势的识别。
介绍
GestureDetector这个类对外提供了两个接口和一个外部类:
- 接口:OnGestureListener,OnDoubleTapListener
- 外部类:SimpleOnGestureListener
这个外部类,其实是两个接口中所有函数的集成,它包含了这两个接口里所有必须要实现的函数而且都已经重写,但所有方法体都是空的;不同点在于:该类是static class,程序员可以在外部继承这个类,重写里面的手势处理方法。
OnGestureListener有下面的几个动作:
- onDown(MotionEvent e):用户按下屏幕就会触发。
- onShowPress(MotionEvent e):如果按下的时间超过瞬间,而且在按下的时候没有松开或者是拖动的,那么onShowPress就会执行,具体这个瞬间是多久,我也不清楚…
- onLongPress(MotionEvent e):长按触摸屏,超过一定时长,就会触发这个事件。
触发顺序:onDown->onShowPress->onLongPress - onSingleTapUp(MotionEvent e):一次单独的轻击抬起操作,也就是轻击一下屏幕,立刻抬起来,才会有这个触发,当然,如果除了Down以外还有其它操作,那就不再是Single操作了,所以也就不会触发这个事件。
触发顺序:
点击一下非常快的(不滑动)Touchup:
onDown->onSingleTapUp->onSingleTapConfirmed
点击一下稍微慢点的(不滑动)Touchup:
onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed - onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) :滑屏,用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发。
参数解释:
e1:第1个ACTION_DOWN MotionEvent
e2:最后一个ACTION_MOVE MotionEvent
velocityX:X轴上的移动速度,像素/秒
velocityY:Y轴上的移动速度,像素/秒 - onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY):在屏幕上拖动事件。无论是用手拖动view,或者是以抛的动作滚动,都会多次触发,这个方法在ACTION_MOVE动作发生时就会触发。
OnDoubleTapListener有下面的几个动作:
- onSingleTapConfirmed(MotionEvent e):单击事件。用来判定该次点击是SingleTap而不是DoubleTap,如果连续点击两次就是DoubleTap手势,如果只点击一次,系统等待一段时间后没有收到第二次点击则判定该次点击为SingleTap而不是DoubleTap,然后触发SingleTapConfirmed事件。
触发顺序是:OnDown->OnsingleTapUp->OnsingleTapConfirmed - onDoubleTap(MotionEvent e):双击事件。
- onDoubleTapEvent(MotionEvent e):双击间隔中发生的动作。指触发onDoubleTap以后,在双击之间发生的其它动作,包含down、up和move事件。
关于onSingleTapConfirmed和onSingleTapUp的区别:onSingleTapUp,只要手抬起就会执行,而对于onSingleTapConfirmed来说,如果双击的话,则onSingleTapConfirmed不会执行。
使用Gesture
使用GestureDetector.OnGestureListener接口
要使用OnGestureListener接口,大致有几步要走:
1、创建OnGestureListener监听函数:
private class gestureListener implements GestureDetector.OnGestureListener{ }
2、创建GestureDetector实例:
构造函数有下面三个,根据需要选择:
GestureDetector gestureDetector=new GestureDetector(GestureDetector.OnGestureListener listener);
GestureDetector gestureDetector=new GestureDetector(Context context,GestureDetector.OnGestureListener listener);
GestureDetector gestureDetector=new GestureDetector(Context context,GestureDetector.SimpleOnGestureListener listener);
注:GestureDetector现在已经是deprecation状态,现在推荐GestureDetectorCompat
GestureDetectorCompat gestureDetectorCompat=new GestureDetectorCompat(Context context,GestureDetector.OnGestureListener listener);
GestureDetectorCompat gestureDetectorCompat=new GestureDetectorCompat(Context context,GestureDetector.OnGestureListener listener, Handler handler);
3、onTouch(View v, MotionEvent event)中拦截,在onTouch()方法中,我们调用GestureDetector的onTouchEvent()方法,将捕捉到的MotionEvent交给GestureDetector来分析是否有合适的callback函数来处理用户的手势
public boolean onTouch(View v, MotionEvent event) { return gestureDetectorCompat.onTouchEvent(event);
}
4、控件绑定
TextView tv = (TextView)findViewById(R.id.tv);
tv.setOnTouchListener(this);
实现代码:
<RelativeLayout 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"> <TextView android:id="@+id/tv" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_margin="50dip" android:background="#76EE00" android:text="Gesture Detector" />
</RelativeLayout>
public class MainActivity extends Activity implements OnTouchListener{ private GestureDetectorCompat mGestureDetectorCompat; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mGestureDetectorCompat = new GestureDetectorCompat(this, new gestureListener()); 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) { return mGestureDetectorCompat.onTouchEvent(event); } private class gestureListener implements GestureDetector.OnGestureListener{ public boolean onDown(MotionEvent e) { showlog("onDown"); Toast.makeText(MainActivity.this, "onDown", Toast.LENGTH_SHORT).show(); return false; } public void onShowPress(MotionEvent e) {showlog("onShowPress"); Toast.makeText(MainActivity.this, "onShowPress", Toast.LENGTH_SHORT).show(); } public boolean onSingleTapUp(MotionEvent e) { showlog("onSingleTapUp"); Toast.makeText(MainActivity.this, "onSingleTapUp", Toast.LENGTH_SHORT).show(); return true; } public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { showlog("onScroll:"+(e2.getX()-e1.getX()) +" "+distanceX); Toast.makeText(MainActivity.this, "onScroll", Toast.LENGTH_LONG).show(); return true; } public void onLongPress(MotionEvent e) { showlog("onLongPress"); Toast.makeText(MainActivity.this, "onLongPress", Toast.LENGTH_LONG).show(); } public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { showlog("onFling"); Toast.makeText(MainActivity.this, "onFling", Toast.LENGTH_LONG).show(); return true; } }; public void showlog(String info) {System.out.print("GestureDetector "+info);}
}
使用GestureDetector.OnDoubleTapListener接口
实现OnDoubleTapListener接口的前提是先实现OnGestureListener接口,其实除了第1步,2、3、4步和上面完全一样,不再赘述,下面看下第一步:
同时创建OnGestureListener和OnDoubleTapListener监听函数:
方法一:新建一个类同时派生自OnGestureListener和OnDoubleTapListener:
private class gestureListener implements GestureDetector.OnGestureListener,GestureDetector.OnDoubleTapListener{ }
方法二:使用GestureDetector.setOnDoubleTapListener();函数设置监听:
/构建GestureDetector实例
mGestureDetector = new GestureDetector(new gestureListener());
private class gestureListener implements GestureDetector.OnGestureListener{
} //设置双击监听器
mGestureDetector.setOnDoubleTapListener(new doubleTapListener());
private class doubleTapListener implements GestureDetector.OnDoubleTapListener{
}
注:大家可以看到无论在方法一还是在方法二中,都需要派生自GestureDetector.OnGestureListener,前面我们说过GestureDetectorCompat 的构造函数,如下:
GestureDetectorCompat gestureDetectorCompat=new GestureDetectorCompat(Context context,GestureDetector.OnGestureListener listener);
GestureDetectorCompat gestureDetectorCompat=new GestureDetectorCompat(Context context,GestureDetector.OnGestureListener listener, Handler handler);
可以看到,它的两个构造函数参数都必须是OnGestureListener的实例。所以要想使用OnDoubleTapListener的几个函数,就必须先实现OnGestureListener。
实现代码:
public class MainActivity extends Activity implements OnTouchListener{ private GestureDetectorCompat mGestureDetectorCompat; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mGestureDetectorCompat = new GestureDetectorCompat(this, new gestureListener()); 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) { return mGestureDetectorCompat.onTouchEvent(event); } private class gestureListener implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener{ public boolean onDown(MotionEvent e) { showlog("onDown"); Toast.makeText(MainActivity.this, "onDown", Toast.LENGTH_SHORT).show(); return false; } public void onShowPress(MotionEvent e) {showlog("onShowPress"); Toast.makeText(MainActivity.this, "onShowPress", Toast.LENGTH_SHORT).show(); } public boolean onSingleTapUp(MotionEvent e) { showlog("onSingleTapUp"); Toast.makeText(MainActivity.this, "onSingleTapUp", Toast.LENGTH_SHORT).show(); return true; } public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { showlog("onScroll:"+(e2.getX()-e1.getX()) +" "+distanceX); Toast.makeText(MainActivity.this, "onScroll", Toast.LENGTH_LONG).show(); return true; } public void onLongPress(MotionEvent e) { showlog("onLongPress"); Toast.makeText(MainActivity.this, "onLongPress", Toast.LENGTH_LONG).show(); } public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { showlog("onFling"); Toast.makeText(MainActivity.this, "onFling", Toast.LENGTH_LONG).show(); return true; }public boolean onSingleTapConfirmed(MotionEvent e) { showlog("onSingleTapConfirmed"); Toast.makeText(MainActivity.this, "onSingleTapConfirmed",Toast.LENGTH_LONG).show(); return true; } public boolean onDoubleTap(MotionEvent e) { showlog("onDoubleTap"); Toast.makeText(MainActivity.this, "onDoubleTap", Toast.LENGTH_LONG).show(); return true; }public boolean onDoubleTapEvent(MotionEvent e) { showlog("onDoubleTapEvent"); Toast.makeText(MainActivity.this, "onDoubleTapEvent", Toast.LENGTH_LONG).show(); return true; }public void showlog(String info) {System.out.print("GestureDetector "+info);}
}
使用GestureDetector.SimpleOnGestureListener类
使用OnGestureListener和OnDoubleTapListener接口,这样需要重载接口所有的方法,适合监听所有的手势,如果我们只想监听某个手势或某几个手势呢,这时候就可以使用SimpleOnGestureListener类了。
它与前两个不同的是:
1、这是一个类,在它基础上新建类的话,要用extends派生而不是用implements继承!
2、OnGestureListener和OnDoubleTapListener接口里的函数都是强制必须重写的,即使用不到也要重写出来一个空函数但在SimpleOnGestureListener类的实例或派生类中不必如此,可以根据情况,用到哪个函数就重写哪个函数,因为SimpleOnGestureListener类本身已经实现了这两个接口的所有函数,只是里面全是空的而已。
public class MainActivity extends Activity implements OnTouchListener { private GestureDetector mGestureDetector; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mGestureDetector = new GestureDetector(new simpleGestureListener()); 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) { return mGestureDetector.onTouchEvent(event); } private class simpleGestureListener extends GestureDetector.SimpleOnGestureListener { /*****OnGestureListener的函数*****/ public boolean onDown(MotionEvent e) { Log.i("MyGesture", "onDown"); Toast.makeText(MainActivity.this, "onDown", Toast.LENGTH_SHORT).show(); return false; } public void onShowPress(MotionEvent e) { Log.i("MyGesture", "onShowPress"); Toast.makeText(MainActivity.this, "onShowPress", Toast.LENGTH_SHORT).show(); } public boolean onSingleTapUp(MotionEvent e) { Log.i("MyGesture", "onSingleTapUp"); Toast.makeText(MainActivity.this, "onSingleTapUp", Toast.LENGTH_SHORT).show(); return true; } /*****OnDoubleTapListener的函数*****/ public boolean onSingleTapConfirmed(MotionEvent e) { Log.i("MyGesture", "onSingleTapConfirmed"); Toast.makeText(MainActivity.this, "onSingleTapConfirmed",Toast.LENGTH_LONG).show(); return true; } public boolean onDoubleTap(MotionEvent e) { Log.i("MyGesture", "onDoubleTap"); Toast.makeText(MainActivity.this, "onDoubleTap", Toast.LENGTH_LONG).show(); return true; } }
}
Demo下载地址
Android的手势操作(Gesture)相关推荐
- Android的手势操作识别
转自:http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2012/1020/448.html Android的手势操作识别 时间:2012-10-20 ...
- android+p手势操作,手势操作哪家强:Android P对比iPhone X
[环球网综合科技报道]据科技博客The Verge5月8日的博文称,Android P给谷歌的操作系统带来了大量的更新设计,其中最为突出的是新近推出的手势操作界面系统.很多人注意到该界面系统与苹果去年 ...
- android 手势旋转,android中手势操作图片的平移、缩放、旋转
在网上搜到很多都是一样的版本,只有平移和缩放的功能.我在搜到的源代码基础上添加了旋转和边界检查的功能. 代码主要分两部分,一个activity一个view,代码如下: [java] package c ...
- 安卓10.0内测版现新版手势操作:很实用
iOS和Android的手势操作进步越来越大.比如谷歌在Android 9 Pie上引入了原生的手势,当然,以小米.华为等为代表的OEM厂商也设计具有自身特色的解决方案. 比如原生安卓9.0上,传统的 ...
- Android 触摸及手势操作GestureDetector
现在的智能手机不敢说百分百的都是触摸屏,也应该是百分之九九以上为触摸屏了,触摸屏为我们操作无键盘.无鼠标的手机系统带来了很多的便利.当用户触摸屏幕时会产生很多的触摸事件,down.up.move等等. ...
- Android 手势拦截的实现(简化水平、垂直手势操作的拦截处理)
这是手势拦截类的源码.注释,也加的随地时,方便阅读理解.在源码后面,会有使用案例. package com.laka.robotdog.widget;import android.content.Co ...
- android touch事件坐标原点,Android onTouch事件与手势操作
触摸,手势操作已经很好的融入了我们的生活.那么Android开发中触摸事件要如何捕捉?如何处理?如何识别手势?事件的传递机制又是怎么样的?下面我们将通过一个小例子来进行这方面的学习. 先看效果图 如上 ...
- Android之GestureDetector-简单手势操作及通过手势缩放图片,我离职后面试收割小米等大厂offer
Android提供了手势检测,并为其提供了相应的监听器,需要用到的类是GestureDetector,其实例代表了一个手势检测器,创建GestureDetector时需要传入一个GestureDete ...
- 索尼xz2android设置向导,索尼为Xperia XZ2 Premium推送Android 9.0 迎来全新手势操作
我们此前报道过,索尼曾计划于10月26日为Xperia XZ Premium,Xperia XZ1和Xperia XZ1 Compact推送Android 9.0更新,但是新系统出现了一些软件级的错误 ...
最新文章
- 合并两个有序链表分析
- Win8 官方培训课程
- java通过commons-fileupload实现多张图片的上传(jsp页面)
- 解决IE8上传文件时javascript取文件的本地路径的问题C:\fakepath\..
- virtualBox文件共享
- /a.out , nohut ./a.out , nohup ./a.out 的区别
- Sqlite3 ---------------用法
- 使用色彩追踪和形态学运算得到图像中感兴趣区域
- 12、箱形图和小提琴图的绘制
- 目前主流的电脑操作系统
- Python练习——用循环求100以内7的倍数
- python opencv灰度转rgb
- 生成一个点开跳出情人节快乐和鲜花的python代码文件
- C++数组求和:关于accumulate函数的使用,简化编写代码量的方法
- ubuntu机械盘写入cannot be copied because you do not have permissions to create it in the destination.
- 超市自动收款机php,自助收银机,超市无人自动收银系统,海信自助POS,自助收款机...
- Android应用代码混淆
- 索尼sony xperia xc刷安卓7、8,解锁root教程
- iOS 视频播放从零开始(二)
- QT使用QMovie播放Gif动画