美文网首页UI
彻底理解Android手势开发GestureDecetor之使用

彻底理解Android手势开发GestureDecetor之使用

作者: 蜗牛猿猿 | 来源:发表于2018-08-26 21:45 被阅读3次

人生和游戏一样,需要不断的打怪升级,等到了一定的等级,也就打开了新的天地!

1、简介

Android手势常见的有单击、双击、长按、滑动、快速滑动、上滑、下滑、左滑、右滑等等。
我们一般重写View的onTouchEvent(MotionEvent event)然后做一些处理。基本的代码格式:

 @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getActionMasked();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                //逻辑处理
                break;
            case MotionEvent.ACTION_MOVE:
                //逻辑处理
                break;
            case MotionEvent.ACTION_UP:
                //逻辑处理
                break;
            default:
                break;
        }
        return true;
    }

这一部分代码的处理基本是一致的。于是强大的谷歌提供了GestureDetector类来简化我们对手势的处理。
下面我们来看看手势开发的API

2、API介绍

手势开发涉及的API

  • GestureDetector(手势管理器)
  • GestureDetector.OnGestureListener(接口,提供一些回调的手势方法)
  • GestureDetector.OnDoubleTapListener(接口,提供一些回调的手势方法)
  • GestureDetector.OnContextClickListener(接口,提供一些回调的手势方法)
  • GestureDetector.SimpleOnGestureListener(空实现了上面的三个手势接口,供开发者重写指定的手势方法)

2.1、GestureDetector API

手势追踪管理器

  • 构造方法
public GestureDetector(Context context, OnGestureListener listener) 
public GestureDetector(Context context, OnGestureListener listener, Handler handler) 
public GestureDetector(Context context, OnGestureListener listener, Handler handler,
            boolean unused) 
构造方法最终都走到了四个参数的构造方法。
参数:context //上下文,基本都要传入的参数
参数:OnGestureListener //传入一个手势回调接口
参数:handler //可以改变内部handler的Looper,下一篇原理篇讲解
参数:unused //这个参数目前源码中没有用到
  • 对外方法
isLongpressEnabled() //是否支持长按手势
setIsLongpressEnabled(boolean isLongpressEnabled)//设置是否允许长按操作
setOnDoubleTapListener(OnDoubleTapListener onDoubleTapListener)//配置这个接口中支持的手势,下面可以看这个接口支持的手势方法
setContextClickListener(OnContextClickListener onContextClickListener)//配置这个接口中支持的手势,下面可以看这个接口支持的手势方法
onTouchEvent(MotionEvent ev)//核心方法,处理各种手势的逻辑在这个里面

2.2、GestureDetector.OnGestureListener

boolean onDown(MotionEvent e)// 用户按下触发,ACTION_DOWN事件,一次手势过程中触发一次
void onShowPress(MotionEvent e)//用户按下但是没有发生move和up,给用户一个可视化的反馈方法,一次手势过程中触发一次
onLongPress(MotionEvent e)//长按事件
onSingleTapUp(MotionEvent e)//单击事件,这个事件发生了,可能会发生双击事件
onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) //快速滑动事件
参数:e1:快速滑动第一个DOWN事件 e2:触发快速滑动的move时间 velocityX:快速滑动事件x方向的速度,单位是px/s,就是每秒划过了多少的像素 velocityY:y方向的速度和x含义一致。
boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)//滑动事件,滑动过程会频繁调用
参数:e1:开始滑动第一个DOWN事件 e2:当前的滑动事件 distanceX:前后两次滑动事件x方向的变化值 distanceY:前后两次滑动事件y方向的变化值

2.3、GestureDetector.OnDoubleTapListener

boolean onSingleTapConfirmed(MotionEvent e)//严格的单击事件,这个事件发生了就不可能会发生双击事件
boolean onDoubleTap(MotionEvent e)//双击事件
boolean onDoubleTapEvent(MotionEvent e)//发生了双击事件,在双击期间ACTION_DOWN、ACTION_MOVE、ACTION_UP都会触发此回调

2.4、GestureDetector.SimpleOnGestureListener

对上面三个接口进行了空实现,手势监听推荐使用这个实现类,这样我们去重写我们需要的手势方法,就不需要每一个手势方法都重写了

3、使用

步骤:
1、构建GestureDetector
2、接管View的onTouchEvent事件处理

示例:

public class MyTestView extends AppCompatImageView {

    private static final String TAG = "MyTestView";
    private GestureDetector gestureDetector;

    public MyTestView(Context context) {
        super(context);
        init();
    }

    public MyTestView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyTestView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        //1、构建GestureDetector对象,传入需要回调的手势接口,这里我们传入手势接口实现类SimpleOnGestureListener
        gestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener() {

            @Override
            public boolean onDown(MotionEvent e) {
                Log.d(TAG, "onDown()");
                //此处必须返回true,否则就只能触发这个事件和onLongPress()事件了
                //其他的事件都不会触发了,这个和android的事件分发机制有关,后面会写一篇关于事件分发。
                return true;
            }

            @Override
            public void onLongPress(MotionEvent e) {
                super.onLongPress(e);
                Log.d(TAG, "onLongPress()");
            }

            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                Log.d(TAG, "onSingleTapUp()");
                return super.onSingleTapUp(e);
            }

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                Log.d(TAG, "onScroll() distanceX:" + distanceX + ",distanceY:" + distanceY);
                ViewGroup viewGroup = (ViewGroup) getParent();
                viewGroup.scrollBy((int) distanceX, (int) distanceY);
                return true;
            }

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                Log.d(TAG, "onFling()");
                return super.onFling(e1, e2, velocityX, velocityY);
            }

        });
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //2、调用gestureDetector.onTouchEvent(event)来接管view的onTouchEvent
        return gestureDetector.onTouchEvent(event);
    }
}

4、手势开发注意点

  • 手势方法中凡是有返回值的方法,这些方法的结果都会返回到view的onTouchEvent方法中,有些方法会影响view的事件分发。
  • onDown方法要返回true,否则就只能触发onDown和onLongPress事件了,其他的都触发不了了,原因就是影响了事件分发过程。
  • onSingleTapUp和onSingleTapConfirmed的区别:
    都理解是单击事件,onSingleTapUp事件发生了,后面还是可能会触发onDoubleTap双击事件;而onSingleTapConfirmed发生就是严格的单击事件后面不会发生onDoubleTap了。所以对于严格的单击事件应该重写onSingleTapConfirmed方法

相关文章

网友评论

    本文标题:彻底理解Android手势开发GestureDecetor之使用

    本文链接:https://www.haomeiwen.com/subject/aftaiftx.html