-
按下(onDown): 刚刚手指接触到触摸屏的那一刹那,就是触的那一下。
-
抛掷(onFling): 手指在触摸屏上迅速移动,并松开的动作。
-
长按(onLongPress): 手指按在持续一段时间,并且没有松开。
-
滚动(onScroll): 手指在触摸屏上滑动。
-
按住(onShowPress): 手指按在触摸屏上,它的时间范围在按下起效,在长按之前。
-
抬起(onSingleTapUp):手指离开触摸屏的那一刹那。
除了这些定义之外,鄙人也总结了一点算是经验的经验吧,在这里和大家分享一下。
-
任何手势动作都会先执行一次按下(onDown)动作。
-
长按(onLongPress)动作前一定会执行一次按住(onShowPress)动作。
-
按住(onShowPress)动作和按下(onDown)动作之后都会执行一次抬起(onSingleTapUp)动作。
-
长按(onLongPress)、滚动(onScroll)和抛掷(onFling)动作之后都不会执行抬起(onSingleTapUp)动作。
当用户触摸屏幕的时候,会产生许多手势,例如down,up,scroll,filing等等,我们知道View类有个View.OnTouchListener内部接口,通过重写他的onTouch(View v, MotionEvent event)方法,我们可以处理一些touch事件,但是这个方法太过简单,如果需要处理一些复杂的手势,用这个接口就会很麻烦(因为我们要自己根据用户触摸的轨迹去判断是什么手势)Android sdk给我们提供了GestureDetector(Gesture:手势Detector:识别)类,通过这个类我们可以识别很多的手势,主要是通过他的onTouchEvent(event)方法完成了不同手势的识别。虽然他能识别手势,但是不同的手势要怎么处理,应该是提供给程序员实现的,因此这个类对外提供了两个接口:OnGestureListener,OnDoubleTapListener,还有一个内部类SimpleOnGestureListener,SimpleOnGestureListener类是GestureDetector提供给我们的一个更方便的响应不同手势的类,这个类实现了上述两个接口(但是所有的方法体都是空的),该类是static class,也就是说它实际上是一个外部类。程序员可以在外部继承这个类,重写里面的手势处理方法。
通过GestureDetector的构造方法可以将SimpleOnGestureListener对象传递进去,这样GestureDetector能处理不同的手势了。
有时候我们并不需要处理上面所有手势,方便起见,Android提供了另外一个类SimpleOnGestureListener实现了如上接口,我们只需要继承SimpleOnGestureListener然后重载感兴趣的手势即可。
对于自定义View,使用手势识别有两处陷阱可能会浪费你的不少时间。
1:View必须设置longClickable为true,否则手势识别无法正确工作,只会返回Down, Show, Long三种手势
2:必须在View的onTouchListener中调用手势识别,而不能像Activity一样重载onTouchEvent,否则同样手势识别无法正确工作
定义GestureDetector时会提示
构造器已经弃用
要加上忽视警告
语句:@SuppressWarnings("deprecation")
GestureDetector会被划上
条横线
代表此语句已经过时
修改:
<span style="font-size: 18px;">随着<a target=_blank target="_blank" class="inner-link decor-none" href="http://zhidao.baidu.com/search?word=Android%20SDK&fr=qb_search_exp&ie=utf8" rel="nofollow" style="color: rgb(45, 100, 179); text-decoration: none;">Android SDK</a><img src="https://i-blog.csdnimg.cn/blog_migrate/fd7ce48e38a4bcdc1d7050201367a908.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />升级<img src="https://i-blog.csdnimg.cn/blog_migrate/86df388af00f5709d701a4ba4711f02c.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" /><img src="http://img.iknow.bdimg.com/question/word/yi3.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />前<img src="https://i-blog.csdnimg.cn/blog_migrate/fd7ce48e38a4bcdc1d7050201367a908.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />某些接口<img src="http://img.iknow.bdimg.com/question/word/ke.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />能有更好、更安全<img src="https://i-blog.csdnimg.cn/blog_migrate/fd7ce48e38a4bcdc1d7050201367a908.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />接口来代替<img src="http://img.iknow.bdimg.com/question/word/stop.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />Android开发团队会把过时<img src="https://i-blog.csdnimg.cn/blog_migrate/fd7ce48e38a4bcdc1d7050201367a908.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />接口标识成deprecated, <img src="https://i-blog.csdnimg.cn/blog_migrate/e1844be2a7cae6c5d66b16a310d84c07.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" /><img src="https://i-blog.csdnimg.cn/blog_migrate/5546c3ab6bee1d9be9918e78ae798c34.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" /><img src="http://img.iknow.bdimg.com/question/word/zai.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />开发文档<img src="http://img.iknow.bdimg.com/question/word/zhong.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />提示使用<img src="http://img.iknow.bdimg.com/question/word/zui.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />新<img src="https://i-blog.csdnimg.cn/blog_migrate/fd7ce48e38a4bcdc1d7050201367a908.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />代替接口<img src="http://img.iknow.bdimg.com/question/word/stop.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" /> <img src="http://img.iknow.bdimg.com/question/word/ni.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />用<img src="http://img.iknow.bdimg.com/question/word/dao.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" /><img src="https://i-blog.csdnimg.cn/blog_migrate/fd7ce48e38a4bcdc1d7050201367a908.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />GestureDetector<img src="https://i-blog.csdnimg.cn/blog_migrate/fd7ce48e38a4bcdc1d7050201367a908.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" /><a target=_blank target="_blank" class="inner-link decor-none" href="http://zhidao.baidu.com/search?word=%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0&fr=qb_search_exp&ie=utf8" rel="nofollow" style="color: rgb(45, 100, 179); text-decoration: none;">构造函数</a><img src="http://img.iknow.bdimg.com/question/word/zai.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />4.1版本<img src="http://img.iknow.bdimg.com/question/word/zhong.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />已经过时<img src="https://i-blog.csdnimg.cn/blog_migrate/86df388af00f5709d701a4ba4711f02c.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" /><img src="http://img.iknow.bdimg.com/question/word/ke.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" /><img src="http://img.iknow.bdimg.com/question/word/yi3.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />使用推荐<img src="https://i-blog.csdnimg.cn/blog_migrate/fd7ce48e38a4bcdc1d7050201367a908.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />: mGestureDetector = new GestureDetector(this, this); // 注意前<img src="https://i-blog.csdnimg.cn/blog_migrate/523d7b72f534642f78277dc572075e9d.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" /><img src="https://i-blog.csdnimg.cn/blog_migrate/9ae775c5ffe95e660ce75bc7318ffbfd.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />this代表<img src="https://i-blog.csdnimg.cn/blog_migrate/fd7ce48e38a4bcdc1d7050201367a908.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" /><img src="http://img.iknow.bdimg.com/question/word/shi.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" /><img src="https://i-blog.csdnimg.cn/blog_migrate/523d7b72f534642f78277dc572075e9d.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" /><img src="https://i-blog.csdnimg.cn/blog_migrate/9ae775c5ffe95e660ce75bc7318ffbfd.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />Context,<img src="https://i-blog.csdnimg.cn/blog_migrate/5546c3ab6bee1d9be9918e78ae798c34.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" /><img src="https://i-blog.csdnimg.cn/blog_migrate/523d7b72f534642f78277dc572075e9d.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" /><img src="https://i-blog.csdnimg.cn/blog_migrate/9ae775c5ffe95e660ce75bc7318ffbfd.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />this代表<img src="https://i-blog.csdnimg.cn/blog_migrate/fd7ce48e38a4bcdc1d7050201367a908.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" /><img src="http://img.iknow.bdimg.com/question/word/shi.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" /><img src="https://i-blog.csdnimg.cn/blog_migrate/523d7b72f534642f78277dc572075e9d.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" /><img src="https://i-blog.csdnimg.cn/blog_migrate/9ae775c5ffe95e660ce75bc7318ffbfd.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />OnGestureListener<img src="http://img.iknow.bdimg.com/question/word/stop.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" /> // Activity继承自Context, 而<img src="http://img.iknow.bdimg.com/question/word/ni.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" /><img src="https://i-blog.csdnimg.cn/blog_migrate/fd7ce48e38a4bcdc1d7050201367a908.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" />activity应该实现了(implements)OnGestureListener接口<img src="http://img.iknow.bdimg.com/question/word/stop.png" class="word-replace" alt="" style="border: 0px; max-width: 100%; vertical-align: middle;" /></span>
2.、具体用法:Android Touch Screen 与传统Click Touch Screen不同,会有一些手势(Gesture),例如Fling,Scroll等等。这些Gesture会使用户体验大大提升。Android中的Gesture识别(detector)是通过GestureDetector.OnGestureListener接口实现的。
首先,Android事件处理机制是基于Listener实现的,比如触摸屏相关的事件,就是通过onTouchListener实现;
其次,所有View的子类都可以通过setOnTouchListener()、setOnKeyListener()等方法来添加对某一类事件的Listener;
第三,Listener一般会以Interface的方式来提供,其中包含一个或多个abstract方法,我们需要实现这些方法来完成onTouch()、onKey()等操作。这样,程序便可以在特定的事件被dispatch到该view的时候,通过callback函数给予适当的响应。
1. Touch Screen Click举例
- public class MyGesture extends Activity implements OnTouchListener {
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- TextView tv = (TextView) findViewById(R.id.tv);
- tv.setOnTouchListener(this);
- }
- public boolean onTouch(View v, MotionEvent event) {
- Toast.makeText(this, "Touch Touch", Toast.LENGTH_SHORT).show();
- return false;
- }
- }
2. 回到今天的重点,当我们捕捉到Touch操作的时候,如何识别出用户的Gesture?这里我们需要GestureDetector.OnGestureListener接口的帮助,代码如下:
- public class MyGesture extends Activity implements OnTouchListener, OnGestureListener {
- private GestureDetector mGestureDetector;
- public MyGesture() {
- mGestureDetector = new GestureDetector(this);
- }
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- TextView tv = (TextView) findViewById(R.id.tv);
- tv.setOnTouchListener(this);
- tv.setFocusable(true);
- tv.setClickable(true);
- tv.setLongClickable(true);
- mGestureDetector.setIsLongpressEnabled(true);
- }
- /*
- * 在onTouch()方法中,我们调用GestureDetector的onTouchEvent()方法,将捕捉到的MotionEvent交给GestureDetector
- * 来分析是否有合适的callback函数来处理用户的手势
- */
- public boolean onTouch(View v, MotionEvent event) {
- return mGestureDetector.onTouchEvent(event);
- }
- // 用户轻触触摸屏,由1个MotionEvent ACTION_DOWN触发
- public boolean onDown(MotionEvent arg0) {
- Log.i("MyGesture", "onDown");
- Toast.makeText(this, "onDown", Toast.LENGTH_SHORT).show();
- return true;
- }
- /*
- * 用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发
- * 注意和onDown()的区别,强调的是没有松开或者拖动的状态
- */
- public void onShowPress(MotionEvent e) {
- Log.i("MyGesture", "onShowPress");
- Toast.makeText(this, "onShowPress", Toast.LENGTH_SHORT).show();
- }
- // 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发
- public boolean onSingleTapUp(MotionEvent e) {
- Log.i("MyGesture", "onSingleTapUp");
- Toast.makeText(this, "onSingleTapUp", Toast.LENGTH_SHORT).show();
- return true;
- }
- // 用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发
- public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
- Log.i("MyGesture", "onFling");
- Toast.makeText(this, "onFling", Toast.LENGTH_LONG).show();
- return true;
- }
- // 用户按下触摸屏,并拖动,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE触发
- public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
- Log.i("MyGesture", "onScroll");
- Toast.makeText(this, "onScroll", Toast.LENGTH_LONG).show();
- return true;
- }
- // 用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发
- public void onLongPress(MotionEvent e) {
- Log.i("MyGesture", "onLongPress");
- Toast.makeText(this, "onLongPress", Toast.LENGTH_LONG).show();
- }
- }
滑屏实现:
- setInAnimation:设置View进入屏幕时候使用的动画,该函数有两个版本:
- setOutAnimation: 设置View退出屏幕时候使用的动画,参数setInAnimation函数一样。
- showNext: 调用该函数来显示FrameLayout里面的下一个View。
- showPrevious: 调用该函数来显示FrameLayout里面的上一个View。