Android手势检测简介

本文参考:启舰博客
一,简介
Android中的手势检测功能主要在GestureDetector这个类当中,所以主要是对GestureDetector这个类的说明。
GestureDetector类对外提供了两个接口和一个外部类,接口:OnGestureListenerOnDoubleTapListener,内部类:SimpleOnGestureListener

二,OnGestureListener接口
手势检测接口,当有down,move,up事件发生时,会回调其中的方法。
OnGestureListener接口重写必须重写6个方法。

public class GestureListenter implements GestureDetector.OnGestureListener {

    @Override
    public boolean onDown(MotionEvent e) {
        return false;
    }

    @Override
    public void onShowPress(MotionEvent e) {

    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        return false;
    }

    @Override
    public void onLongPress(MotionEvent e) {

    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        return false;
    }
}
方法含义
OnDown(MotionEvent e)发生down事件时会立即调用
onShowPress(MotionEvent e)用户触发down事件,没触发move或yet事件,且down事件发生时间超过瞬间则调用
onLongPress(MotionEvent e)down事件发生时间超过一定时长,会调用
onSingleTapUp(MotionEvent e)单独的轻击会调用
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)滑屏调用,且会调用多次
实际操作调用顺序
轻击onDown() - onSingleTapup()
短按onDown() - onShowPress() - onSingleTapUp()
长按onDown() - onShowPress() - onLongPress()
短按慢划onDown() - onShowPress() - 多个onScroll() -onFling()
快划onDown() - 多个onScroll() - onFling()
长按滑动onDown() - onShowPress() - onLongPress()

总结:当点击时接触屏幕时间超过一定时间会触发onShowPress(),可以作为是否误触的一个判决条件。

public class MainActivity extends AppCompatActivity {

    private GestureDetector mGestureDetector;
    TextView mTextTv;

    @SuppressLint("ClickableViewAccessibility")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mGestureDetector = new GestureDetector(new GestureListenter());
        mTextTv = findViewById(R.id.tv_text);
        mTextTv.setFocusable(true);
        mTextTv.setClickable(true);
        mTextTv.setLongClickable(true);
        mTextTv.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return mGestureDetector.onTouchEvent(event);
            }
        });
    }
}

public class GestureListenter implements GestureDetector.OnGestureListener {

    private static final String TAG = "GestureListenter";

    @Override
    public boolean onDown(MotionEvent e) {
        Log.i(TAG, "onDown: ");
        return true;
    }

    @Override
    public void onShowPress(MotionEvent e) {
        Log.i(TAG, "onShowPress: ");
    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        Log.i(TAG, "onSingleTapUp: ");
        return true;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        Log.i(TAG, "onScroll: ");
        return true;
    }

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

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

需要注意的是onDown()方法应该返回true,否则会导致在慢速滑动况下结束时不会调用onFling()方法,我刚才踩到了。

三,OnDoubleTapListener接口
OnDoubleTapListener是检测屏幕双击的接口。重写时需要重写3个方法

public class DoubleTapListener implements GestureDetector.OnDoubleTapListener {
    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onDoubleTap(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onDoubleTapEvent(MotionEvent e) {
        return false;
    }
}
方法含义
onSingleTapConfirmed(MotionEvent e)单击确认触发
onDoubleTap(MotionEvent e)双击时触发
onDoubleTapEvent(MotionEvent e)双击间隔中发生的动作。指触发onDoubleTap以后,在双击之间发生的其它动作,包含down、up和move事件。
public class DoubleTapListener implements GestureDetector.OnDoubleTapListener {

    private static final String TAG = "WillScorpio";

    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        Log.i(TAG, "onSingleTapConfirmed: ");
        return true;
    }

    @Override
    public boolean onDoubleTap(MotionEvent e) {
        Log.i(TAG, "onDoubleTap: ");
        return true;
    }

    @Override
    public boolean onDoubleTapEvent(MotionEvent e) {
        Log.i(TAG, "onDoubleTapEvent: ");
        return true;
    }
}

为了便于观看log,将ListenerTAG设置为一样的。

mGestureDetector.setOnDoubleTapListener(new DoubleTapListener());

再通过上面的代码设置OnDoubleTapListener

事件调用过程
轻点onDown() - onSingleTapUp() - onSingleTapConfirmed()
单击onDown() - onShowPress() - onSingleTapUp() - onSingleTapConfirmed()
轻击两次onDown() - onSingleTapUp() - onDoubleTap() - onDoubleTapEvent() - onDown() - onDoubleTapEvent()
单击两次onDown() - onShowPress()- onSingleTapUp() - onDoubleTap() - onDoubleTapEvent() - onDown() - onDoubleTapEvent()
第一次点击第二次点上滑动onDown() - onShowPress() - onSingleTapUp() - onDoubleTap() - onDoubleTapEvent() - onDown() - 多个onDoubleTapEvent()

总结:1.在第二下点击时,先触发OnDoubleTap,然后再触发OnDown(第二次点击)。
2.在多个onDoubleTapEvent()之间可能会有onShowPress(),onShowPress()不应该作为重要参数。

四,SimpleOnGestureListener内部类
SimpleOnGestureListenerGestureDetector的内部类,它实现了OnGestureListenerOnDoubleTapListener接口,这样做的好处是如果我们只准备重写其中几个方法,不想重写所有接口方法或准备重写所有方法,便可以选择这个内部类,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);

在这里插入图片描述
五,识别左右滑动

识别左右滑动在onFling()这个函数中,e1是刚开始的MotionEvente2是最后的MotionEvent,正常滑动时没问题,但如果做如下图的滑动,会造成混淆。
在这里插入图片描述

public class GestureListenter implements GestureDetector.OnGestureListener {

    private static final String TAG = "WillScorpio";
    final int FLING_MIN_DISTANCE = 100;
    final int FLING_MIN_VELOCITY = 200;


    @Override
    public boolean onDown(MotionEvent e) {
        Log.i(TAG, "onDown: ");
        return true;
    }

    @Override
    public void onShowPress(MotionEvent e) {
        Log.i(TAG, "onShowPress: ");
    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        Log.i(TAG, "onSingleTapUp: ");
        return true;
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        Log.i(TAG, "onScroll: ");
        return true;
    }

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

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        if (e1.getX() - e2.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) > FLING_MIN_VELOCITY) {
            Log.i(TAG, "onFling: Left");
        }
        if (e2.getX() - e1.getX() > FLING_MIN_DISTANCE && Math.abs(velocityX) > FLING_MIN_VELOCITY) {
            Log.i(TAG, "onFling: Right");
        }
        return true;
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值