Android 手势拦截的实现(简化水平、垂直手势操作的拦截处理)

版权声明:本文为博主原创文章,未经博主允许,也可以随意转载。但麻烦,加个友情链接,增加点人气。 https://blog.csdn.net/l_o_s/article/details/79698402

这是手势拦截类的源码。注释,也加的随地时,方便阅读理解。在源码后面,会有使用案例。

package com.laka.robotdog.widget;

import android.content.Context;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;


/**
 * @Author Lyf
 * @CreateTime 2018/3/26
 * @Description 手势拦截类。用于简化,拦截水平或垂直的手势。
 **/
public class InterceptTouchListener implements View.OnTouchListener {

    // 上下文,建议用全局上下文
    // private Context mContext;

    // 按压到屏幕时的坐标
    private float[] mCoordinate;
    // 最小的滑动距离,不同手机不同
    private int mMinimumSlop;

    // 两个回调接口,当触发水平或垂直手势时,会被调用
    private OnHorizontalGestureListener mOnHorizontalGestureListener;
    private OnVerticalGestureListener mOnVerticalGestureListener;

    public InterceptTouchListener(Context mContext) {

        mCoordinate = new float[2];
        mMinimumSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {

            case MotionEvent.ACTION_DOWN:
                // 保存按压到屏幕时的坐标
                setCoordinate(event);
                break;
            case MotionEvent.ACTION_MOVE:
                if (isClickEvent(event)) {
                    // 不处理点击事件,因为部分机型的点击事件会触发ACTION_MOVE,所以这里要做过滤。
                    break;
                } else {

                    if (mOnHorizontalGestureListener != null
                            && isHorizontalGestureEvent(event)) {
                        return mOnHorizontalGestureListener.onHorizontalGesture(event.getX(), mCoordinate[0]);
                    }

                    if (mOnVerticalGestureListener != null
                            && isVerticalGestureEvent(event)) {
                        return mOnVerticalGestureListener.onVerticalGesture(event.getY(), mCoordinate[1]);
                    }

                }
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return false;
    }

    /**
     * @return return true 如果用户当前正在进行水平方向的手势操作
     */
    private boolean isHorizontalGestureEvent(MotionEvent event) {

        float slopX = getSlopX(event);
        // 滑动距离,必须大于最小滑动距离。
        return slopX > mMinimumSlop && slopX >= getSlopY(event);
    }

    /**
     * @return return true 如果用户当前正在进行垂直方向的手势操作
     */
    private boolean isVerticalGestureEvent(MotionEvent event) {

        float slopY = getSlopY(event);
        // 滑动距离,必须大于最小滑动距离。
        return slopY > mMinimumSlop && getSlopX(event) < slopY;
    }

    /**
     * @return return true 如果并没有移动,只是点击而已。
     */
    private boolean isClickEvent(MotionEvent event) {
        return getSlopX(event) == 0 && getSlopY(event) == 0;
    }

    /**
     * 保存坐标
     */
    private void setCoordinate(MotionEvent event) {

        mCoordinate[0] = event.getX();
        mCoordinate[1] = event.getY();
    }

    /**
     * @return 水平滑动的距离
     */
    private float getSlopX(MotionEvent event) {
        return Math.abs(event.getX() - mCoordinate[0]);
    }

    /**
     * @return 垂直滑动的距离
     */
    private float getSlopY(MotionEvent event) {
        return Math.abs(event.getY() - mCoordinate[1]);
    }

    public InterceptTouchListener setOnHorizontalGestureListener(OnHorizontalGestureListener mOnHorizontalGestureListener) {
        this.mOnHorizontalGestureListener = mOnHorizontalGestureListener;
        return this;
    }

    public InterceptTouchListener setOnVerticalGestureListener(OnVerticalGestureListener mOnVerticalGestureListener) {
        this.mOnVerticalGestureListener = mOnVerticalGestureListener;
        return this;
    }

    public interface OnHorizontalGestureListener {

        /**
         * 当用户在进行水平方向的操作时,该方法会被调用
         *
         * @param currentX 当前的X坐标
         * @param lastX    上一次的X坐标
         * @return return true 如果要拦截事件。
         */
        boolean onHorizontalGesture(float currentX, float lastX);
    }

    public interface OnVerticalGestureListener {
        /**
         * 当用户在进行垂直方向的操作时,该方法会被调用
         *
         * @param currentY 当前的Y坐标
         * @param lastY    上一次的Y坐标
         * @return return true 如果要拦截事件。
         */
        boolean onVerticalGesture(float currentY, float lastY);
    }

}

使用案例

      // 设置触摸事件,mDrawer可以是任意需要设置OnTouchListener的View.
      mDrawer.setOnTouchListener(new InterceptTouchListener(this)
                .setOnHorizontalGestureListener(new InterceptTouchListener
                .OnHorizontalGestureListener() {
                    @Override
                    public boolean onHorizontalGesture(float currentX, float lastX) {
                        // 从左向右滑
                        if (currentX - lastX > 0) {
                            if (!mDrawer.isDrawerOpen(mDrawerContentView)) {
                                mDrawer.openDrawer(Gravity.START);
                            }
                        } else {
                            // 从右向左滑
                            if (mDrawer.isDrawerOpen(mDrawerContentView)) {
                                mDrawer.closeDrawer(Gravity.START);
                            }
                        }
                        return true;

                    }
                }));

———————————————————————————————————Lambda语法版——————————————————————————————————————————————

        //  Lambda语法版
        mDrawer.setOnTouchListener(new InterceptTouchListener(this)
                .setOnHorizontalGestureListener((currX, lastX) -> {

                    // 从左向右滑
                    if (currX - lastX > 0) {
                        if (!mDrawer.isDrawerOpen(mDrawerContentView)) {
                            mDrawer.openDrawer(Gravity.START);
                        }
                    } else {
                        // 从右向左滑
                        if (mDrawer.isDrawerOpen(mDrawerContentView)) {
                            mDrawer.closeDrawer(Gravity.START);
                        }
                    }
                    return true;
                }));

从使用上,可以看出。这个类,简化了手势操作的判断。你可以把你的精力专注于:当水平或垂直事件,被触发时。你要做什么业务,以及需不需要拦截手势事件就行。下面是英文注释版本:

这是,英文注释版本:

package com.laka.robotdog.widget;

import android.content.Context;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;


/**
 * @Author Lyf
 * @CreateTime 2018/3/26
 * @Description An InterceptTouchListener is a class for intercepting Gestures.
 * For Instance, moving finger from top to down or from left to right on Screen.
 **/
public class InterceptTouchListener implements View.OnTouchListener {

    // Context, It also can be an Application Context.
    // private Context mContext;

    // Coordinate of the point You pressed on Screen.
    private float[] mCoordinate;
    // Distance in pixels a touch can wander before we think the user is scrolling
    private int mMinimumSlop;

    // These interfaces definition for callback When the user vertically or horizontally moving his finger on the screen.
    private OnHorizontalGestureListener mOnHorizontalGestureListener;
    private OnVerticalGestureListener mOnVerticalGestureListener;

    public InterceptTouchListener(Context mContext) {

        mCoordinate = new float[2];
        mMinimumSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {

            case MotionEvent.ACTION_DOWN:
                // Save the coordinate of the point you were click on the screen.
                setCoordinate(event);
                break;
            case MotionEvent.ACTION_MOVE:
                if (isClickEvent(event)) {
                    // We don't deal with click Event in here.
                    break;
                } else {

                    if (mOnHorizontalGestureListener != null
                            && isHorizontalGestureEvent(event)) {
                        return mOnHorizontalGestureListener.onHorizontalGesture(event.getX(), mCoordinate[0]);
                    }

                    if (mOnVerticalGestureListener != null
                            && isVerticalGestureEvent(event)) {
                        return mOnVerticalGestureListener.onVerticalGesture(event.getY(), mCoordinate[1]);
                    }

                }
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return false;
    }

    /**
     * Horizontal Gesture Event is an event, from left to right or a reverse action.
     *
     * @return return true if the user is moving his finger from left to right or from right to left.
     */
    private boolean isHorizontalGestureEvent(MotionEvent event) {
        float slopX = getSlopX(event);
        return slopX > mMinimumSlop && slopX >= getSlopY(event);
    }

    /**
     * Horizontal Gesture Event is an event, from top to down or a reverse action.
     *
     * @return return true if the user is moving his finger from top to down or from down to top.
     */
    private boolean isVerticalGestureEvent(MotionEvent event) {
        float slopY = getSlopY(event);
        return slopY > mMinimumSlop && getSlopX(event) < slopY;
    }

    /**
     * Some phones will perform the ACTION_MOVE action When the user just clicked the screen.
     * This shouldn't be. Anyway, We gotta deal with it. So that I created this method.
     *
     * @return return true if the action is just a pressed action.
     */
    private boolean isClickEvent(MotionEvent event) {
        return getSlopX(event) == 0 && getSlopY(event) == 0;
    }

    private void setCoordinate(MotionEvent event) {

        mCoordinate[0] = event.getX();
        mCoordinate[1] = event.getY();
    }

    /**
     * Distance in horizontal orientation of the user moving on.
     */
    private float getSlopX(MotionEvent event) {
        return Math.abs(event.getX() - mCoordinate[0]);
    }

    /**
     * Distance in vertical orientation of the user moving on.
     */
    private float getSlopY(MotionEvent event) {
        return Math.abs(event.getY() - mCoordinate[1]);
    }

    public InterceptTouchListener setOnHorizontalGestureListener(OnHorizontalGestureListener mOnHorizontalGestureListener) {
        this.mOnHorizontalGestureListener = mOnHorizontalGestureListener;
        return this;
    }

    public InterceptTouchListener setOnVerticalGestureListener(OnVerticalGestureListener mOnVerticalGestureListener) {
        this.mOnVerticalGestureListener = mOnVerticalGestureListener;
        return this;
    }

    public interface OnHorizontalGestureListener {
        /**
         * Called When user is moving his finger in horizontally orientation.
         *
         * @return return true if you want to intercept the touch Event.
         */
        boolean onHorizontalGesture(float currentX, float lastX);
    }

    /**
     * Called When user is moving his finger in vertically orientation.
     *
     * @return return true if you want to intercept the touch Event.
     */
    public interface OnVerticalGestureListener {
        boolean onVerticalGesture(float currentY, float lastY);
    }

}

Thank you for reading my posted. If you have any questions, You can comment below. Thank you.

猜你喜欢

转载自blog.csdn.net/l_o_s/article/details/79698402