Android GestureDetector和SimpleOnGestureListener的使用

1. 当用户触摸屏幕的时候,会产生许多手势,例如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能处理不同的手势了。

2.具体用法:

2.1

DefaultGestureListener.java
private class DefaultGestureListener extends SimpleOnGestureListener{        @Override        public boolean onSingleTapUp(MotionEvent e) {            return false;        }        @Override        public void onLongPress(MotionEvent e) {         }        /**         * @param e1 The first down motion event that started the scrolling.           @param e2 The move motion event that triggered the current onScroll.           @param distanceX The distance along the X axis(轴) that has been scrolled since the last call to onScroll. This is NOT the distance between e1 and e2.           @param distanceY The distance along the Y axis that has been scrolled since the last call to onScroll. This is NOT the distance between e1 and e2.                       无论是用手拖动view,或者是以抛的动作滚动,都会多次触发 ,这个方法在ACTION_MOVE动作发生时就会触发 参看GestureDetector的onTouchEvent方法源码         * */        @Override        public boolean onScroll(MotionEvent e1, MotionEvent e2,                float distanceX, float distanceY) {            return false;        }        /**         * @param e1 第1个ACTION_DOWN MotionEvent 并且只有一个         * @param e2 最后一个ACTION_MOVE MotionEvent          * @param velocityX X轴上的移动速度,像素/秒           * @param velocityY Y轴上的移动速度,像素/秒         * 这个方法发生在ACTION_UP时才会触发 参看GestureDetector的onTouchEvent方法源码         *          * */        @Override        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,                float velocityY) {            return false;        }        @Override        public void onShowPress(MotionEvent e) {         }        @Override        public boolean onDown(MotionEvent e) {            return false;        }        @Override        public boolean onDoubleTap(MotionEvent e) {            return false;        }        @Override        public boolean onDoubleTapEvent(MotionEvent e) {            return false;        }        /**         * 这个方法不同于onSingleTapUp,他是在GestureDetector确信用户在第一次触摸屏幕后,没有紧跟着第二次触摸屏幕,也就是不是“双击”的时候触发         * */        @Override        public boolean onSingleTapConfirmed(MotionEvent e) {            return false;        }     }

  

2.2

public GestureDetector (Context context,GestureDetector.OnGestureListener listener) //通过构造方法将手势响应交给手势识别类

2.3

在OnTouchListener的onTouch方法中

private OnTouchListener gestureTouchListener = new OnTouchListener() {        @Override        public boolean onTouch(View v, MotionEvent event) {            return gDetector.onTouchEvent(event);        }    };

 ok,到此为止就结束了.

3.案例:

Res.java
package com.android; import android.app.Activity;import android.os.Bundle;import android.util.Log;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.View;import android.widget.Button; public class Res extends Activity implements View.OnTouchListener {    Button btn = null;    private GestureDetector mGestureDetector = null;     /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        btn = (Button) findViewById(R.id.button);        btn.setOnTouchListener(this);        mGestureDetector = new GestureDetector(this, new LearnGestureListener());    }     public boolean onTouch(View view, MotionEvent event) {        return mGestureDetector.onTouchEvent(event);    }     class LearnGestureListener extends GestureDetector.SimpleOnGestureListener {        @Override        public boolean onSingleTapUp(MotionEvent ev) {            Log.d("DEBUG","onSingleTapUp");            return true;        }         @Override        public void onShowPress(MotionEvent ev) {            Log.d("DEBUG","onShowPress");        }         @Override        public void onLongPress(MotionEvent ev) {            Log.d("DEBUG","onLongPress");        }         @Override        public boolean onScroll(MotionEvent e1, MotionEvent e2,                float distanceX, float distanceY) {            Log.d("DEBUG","onScroll");            return true;        }         @Override        public boolean onDown(MotionEvent ev) {            Log.d("DEBUG","onDownd");            return true;        }         @Override        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,                float velocityY) {            Log.d("DEBUG","onFling");            return true;        }        public boolean onDoubleTap(MotionEvent event){            Log.d("DEBUG","onDoubleTap");            return true;        }    } }

  

4.遇到的问题:
1. onFling(***)无法触发
通过设置 mListView.setLongClickable(true);即可(我处理的是ListView的手势事件),只有这样,view才能够处理不同于Tap(轻触)的hold(即ACTION_MOVE,或者多个ACTION_DOWN),我们同样可以通过layout定义中的android:longClickable来做到这一点。
2. 用户长按手机屏幕,就会触发长按事件,离开屏幕时,就会触发up事件,但是SimpleOnGestureListener没有对longPress事件的up事件对外提供接口
解决办法:
类似于这样,截获up事件,因为所有的都是有OnTouchListener 先获得,然后传递给SimpleOnGestureListener的,这里有一点必须要注意:
截获到up事件,我们进行了处理后,必须要将这个事件再交给SimpleOnGestureListener处理,虽然我们只截获长按事件的up,但是SimpleOnGestureListener对于长按事件的up也做了一些处理,只是没有对外提供接口。

做了什么处理: 

if (mInLongPress) {                mHandler.removeMessages(TAP);                mInLongPress = false;}

如果不交给SimpleOnGestureListener处理,那么单击动作也会触发onLongPress方法。

private OnTouchListener gestureTouchListener = new OnTouchListener() {        @Override        public boolean onTouch(View v, MotionEvent event) {            switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                return gDetector.onTouchEvent(event);           case MotionEvent.ACTION_UP:                MyGesture.FlagInfo info = mGesture.getFlagInfo();                if(info.isConnected==true){                    int firstVisiblePosition = mListView.getFirstVisiblePosition();                    View view = mListView.getChildAt(info.position-firstVisiblePosition);                    if(view!=null){                        view.setBackgroundResource(R.drawable.listitem_background_blue);                        info.isConnected = false;                    }                }                return gDetector.onTouchEvent(event);            case MotionEvent.ACTION_MOVE:                return gDetector.onTouchEvent(event);            }            return false;         }    };

总结:

1. 点击屏幕上的某项的执行流程 有两种情况,一种是时间很短,一种时间稍长
时间很短:onDown——–》onSingleTapUp——–》onSingleTapConfirmed
时间稍长:onDown——–》onShowPress——》onSingleTapUp——–》onSingleTapConfirmed
2. 长按事件
onDown——–》onShowPress——》onLongPress
3.抛:手指触动屏幕后,稍微滑动后立即松开
onDown—–》onScroll—-》onScroll—-》onScroll—-》………—–>onFling
4.拖动
onDown——》onScroll—-》onScroll——》onFiling
注意:有的时候会触发onFiling,但是有的时候不会触发,个人理解是人的动作不标准所致。

更多相关文章

  1. android 音量调整
  2. Android手势操作(一)
  3. android Studio listView 简单的用法
  4. GestureDetector使用实例
  5. Android手势操作(三)
  6. android 如何利用手势放大和缩小一个图片?
  7. Building Local Unit Tests
  8. DrawLayout几个注意点
  9. android recycleview 中禁止多点触发

随机推荐

  1. IPv4 没有用完!
  2. Fabric组织动态管理
  3. 2021-03-18:给定一个字符串str,只由‘X’和
  4. 混合云场景下金融级中间件自动化运维平台
  5. 终端安全发展
  6. 人生苦短,56岁的地产大佬潘石屹学 Python!
  7. Git 从入坑到成神,你只需要敲一遍命令!
  8. 何所思:为什么说,技术的路上,弯道超车总是一
  9. 企业级数据分析体系的最佳实践
  10. 网易数据库运维自动化演进与 AIOps 探索