GestureDetector 手势识别器源码详解

      相信大家都用过GestureDetector手势识别器,一般常用场景都是在自定义控件当中对滑动手势操作。最近也用到了手势识别器就看了源码翻译一下,再此做个记录,希望能帮助到大家。首先我们要知道GestureDetector继承的是Object类,也是在android.view包下面,那我们就继续看一下这个类的一些方法和接口。  
/**
 * Detects various gestures and events using the supplied {@link MotionEvent}s.
 * The {@link OnGestureListener} callback will notify users when a particular
 * motion event has occurred. This class should only be used with {@link MotionEvent}s
 * reported via touch (don't use for trackball events).
 *
 * To use this class:
 * <ul>
 *  <li>Create an instance of the {@code GestureDetector} for your {@link View}
 *  <li>In the {@link View#onTouchEvent(MotionEvent)} method ensure you call
 *          {@link #onTouchEvent(MotionEvent)}. The methods defined in your callback
 *          will be executed when the events occur.
 *  <li>If listening for {@link OnContextClickListener#onContextClick(MotionEvent)}
 *          you must call {@link #onGenericMotionEvent(MotionEvent)}
 *          in {@link View#onGenericMotionEvent(MotionEvent)}.
 * </ul>
 */
这个类的解释:
通过系统提供的MotionEvent来监测各种手势和(触摸)事件。当一个指定的手势事件发生时,GestureDetector.OnGestureListener回调函数将通告用户。这个类仅仅处理由触摸引发的MotionEvent(不能处理由轨迹球引发的事件)。要使用这个类需执行以下操作:
1.为你的View建立一个GestureDetector实例。
2.在View的onTouchEvent(MotionEvent)方法里确保调用(GestureDetector的)onTouchEvent(MotionEvent)方法。当相关事件发生时,定义在回调函数里的方法将被执行。
   几个接口里的方法:
public interface OnGestureListener{
        /**
         * Notified when a tap occurs with the down {@link MotionEvent}
         * that triggered it. This will be triggered immediately for
         * every down event. All other events should be preceded by this.
         *
         * @param e The down motion event.向下运动事件。
         */当发生轻击时发生向下{@link MotionEvent}触发它。这将立即触发每个下降事件。 所有其他事件应该在这之前。
        boolean onDown(MotionEvent e);

        /**
         * The user has performed a down {@link MotionEvent} and not performed
         * a move or up yet. This event is commonly used to provide visual
         * feedback to the user to let them know that their action has been
         * recognized i.e. highlight an element.
         *
         * @param e The down motion event 向下运动事件。
用户已执行了{@link MotionEvent},但未执行移动或向上。 此事件通常用于提供可视化反馈给用户,让他们知道他们的行动已经识别,即突出显示一个元素。
        void onShowPress(MotionEvent e);

        /**
         * Notified when a tap occurs with the up {@link MotionEvent}
         * that triggered it.
         *
         * @param e The up motion event that completed the first tap
         * @return true if the event is consumed, else false
当发生轻击时通知{@link MotionEvent}触发它。 @param e完成第一次敲击的向上运动事件 @如果事件被消耗则返回true,否则为false
        boolean onSingleTapUp(MotionEvent e);

        /**
         * Notified when a scroll occurs with the initial on down {@link MotionEvent} and the
         * current move {@link MotionEvent}. The distance in x and y is also supplied for
         * convenience.
         *
         * @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 {@code e1}
         *              and {@code 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 {@code e1}
         *              and {@code e2}.
         * @return true if the event is consumed, else false
         */在初始向下滚动时发生滚动{@link MotionEvent}和
          *当前移动{@link MotionEvent}。 还提供x和y中的距离
          * 方便。
          *:
          * @param e1开始滚动的第一个向下运动事件。
          * @param e2触发当前onScroll的移动运动事件。
          * @param distanceX自上次以来滚动的X轴上的距离
          *调用onScroll。 这不是{@code e1}
          *和{@code e2}。
          * @param distanceY自上次以来滚动的Y轴上的距离
          *调用onScroll。 这不是{@code e1}
          *和{@code e2}。
          * @如果事件被消耗则返回true,否则为false
        boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);
        /**
         * Notified when a long press occurs with the initial on down {@link MotionEvent}
         * that trigged it.
         *
         * @param e The initial on down motion event that started the longpress.
         */当长按初始化时,通知{@link MotionEvent}
          *触发它。
          * @param e启动长按的初始向下运动事件
        void onLongPress(MotionEvent e);

        /**
         * Notified of a fling event when it occurs with the initial on down {@link MotionEvent}
         * and the matching up {@link MotionEvent}. The calculated velocity is supplied along
         * the x and y axis in pixels per second.
         *
         * @param e1 The first down motion event that started the fling.
         * @param e2 The move motion event that triggered the current onFling.
         * @param velocityX The velocity of this fling measured in pixels per second
         *              along the x axis.
         * @param velocityY The velocity of this fling measured in pixels per second
         *              along the y axis.
         * @return true if the event is consumed, else false
         */通知初始化时发生的fling事件{@link MotionEvent}
          *和匹配{@link MotionEvent}。 沿着计算的速度提供
          * x和y轴以像素每秒为单位。
          *:
          * @param e1启动fling的第一个向下运动事件。
          * @param e2触发当前onFling的移动运动事件。
          * @param velocityX此fling的速度以像素每秒为单位测量
          *沿x轴。
          * @param velocityY此fling的速度以像素每秒为单位测量
          *沿y轴。
          * @如果事件被消耗则返回true,否则为false
        boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
    }
/**
     * The listener that is used to notify when a double-tap or a confirmed
     * single-tap occur.
     */用于在双击或确认时通知的侦听器
      *单击发生。
    public interface OnDoubleTapListener {
        /**
         * Notified when a single-tap occurs.
         * <p>
         * Unlike {@link OnGestureListener#onSingleTapUp(MotionEvent)}, this
         * will only be called after the detector is confident that the user's
         * first tap is not followed by a second tap leading to a double-tap
         * gesture.
         *
         * @param e The down motion event of the single-tap.
         * @return true if the event is consumed, else false
         */发生单击时通知。
          *不像{@link OnGestureListener#onSingleTapUp(MotionEvent)},这个
          *将只有在检测器确信用户的调用
          *第一次敲击之后不是第二次敲击导致双击
          *手势。
          *:
          * @param e单击的向下运动事件。
          * @如果事件被消耗则返回true,否则为false
        boolean onSingleTapConfirmed(MotionEvent e);
 
        /**
         * Notified when a double-tap occurs.
         *
         * @param e The down motion event of the first tap of the double-tap.
         * @return true if the event is consumed, else false
         */发生双击时通知。
          * @param e双击的第一次敲击的向下运动事件。
          * @如果事件被消耗则返回true,否则为false
        boolean onDoubleTap(MotionEvent e);

        /**
         * Notified when an event within a double-tap gesture occurs, including
         * the down, move, and up events.
         *
         * @param e The motion event that occurred during the double-tap gesture.
         * @return true if the event is consumed, else false
         */在双击手势中发生事件时通知,包括
          *向下,移动和向上事件。
          * @param e双击手势期间发生的运动事件。
          * @如果事件被消耗则返回true,否则为false
        boolean onDoubleTapEvent(MotionEvent e);
    }

 /**
     * The listener that is used to notify when a context click occurs. When listening for a
     * context click ensure that you call {@link #onGenericMotionEvent(MotionEvent)} in
     * {@link View#onGenericMotionEvent(MotionEvent)}.
     */他用于在发生上下文点击时通知的侦听器。 当听时
      *上下文点击确保你调用{@link #onGenericMotionEvent(MotionEvent)}
      * {@link View#onGenericMotionEvent(MotionEvent)}。
    public interface OnContextClickListener {
        /**
         * Notified when a context click occurs.
         * @param e The motion event that occurred during the context click.
         * @return true if the event is consumed, else false
         */发生上下文单击时通知。
          * @param e在上下文单击期间发生的运动事件。
          * @如果事件被消耗则返回true,否则为false
        boolean onContextClick(MotionEvent e);
    }

     GestureDetector的接口就只有这三个,包括里面都有一些常用的方法。但是在我们实际开发中,如果我们需要实现这3个接口,我们不必一个一个的实现,因为在android系统中已经定义了一个SimpleOnGestureListener类帮我们实现了这几个接口,继续往下看,最后我会贴出一段代码怎么使用这个类。
/**
     * A convenience class to extend when you only want to listen for a subset
     * of all the gestures. This implements all methods in the
     * {@link OnGestureListener}, {@link OnDoubleTapListener}, and {@link OnContextClickListener}
     * but does nothing and return {@code false} for all applicable methods.
     */一个方便的类,当你只想监听一个子集时扩展
      *所有的手势。 这实现了所有的方法
      * {@link OnGestureListener},{@link OnDoubleTapListener}和{@link OnContextClickListener}
      *但什么都不做,并返回{@code false}所有适用的方法。
    public static class SimpleOnGestureListener implements OnGestureListener, OnDoubleTapListener,
            OnContextClickListener {
        public boolean onSingleTapUp(MotionEvent e) {
            return false;
        }
        public void onLongPress(MotionEvent e) {
        }
        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                float distanceX, float distanceY) {
            return false;
        }
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                float velocityY) {
            return false;
        }
        public void onShowPress(MotionEvent e) {
        }
        public boolean onDown(MotionEvent e) {
            return false;
        }

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


        public boolean onDoubleTapEvent(MotionEvent e) {
            return false;
        }


        public boolean onSingleTapConfirmed(MotionEvent e) {
            return false;
        }


        public boolean onContextClick(MotionEvent e) {
            return false;
        }
    }
    一些构造方法:
 /**
     * Creates a GestureDetector with the supplied listener.
     * This variant of the constructor should be used from a non-UI thread 
     * (as it allows specifying the Handler).
     * 
     * @param listener the listener invoked for all the callbacks, this must
     * not be null.
     * @param handler the handler to use
     *
     * @throws NullPointerException if either {@code listener} or
     * {@code handler} is null.
     *
     * @deprecated Use {@link #GestureDetector(android.content.Context,
     *      android.view.GestureDetector.OnGestureListener, android.os.Handler)} instead.
     */使用提供的侦听器创建GestureDetector。
      *此构造函数的变体应该从非UI线程中使用
      *(因为它允许指定处理程序)。
      * @param listener为所有回调调用的监听器,这必须
      *不能为null。
      * @param handler使用的处理程序
      * @throws NullPointerException如果{@code listener}或
      * {@code handler}为null。
    @Deprecated
    public GestureDetector(OnGestureListener listener, Handler handler) {
        this(null, listener, handler);
    }
/**
     * Creates a GestureDetector with the supplied listener.
     * You may only use this constructor from a UI thread (this is the usual situation).
     * @see android.os.Handler#Handler()
     * 
     * @param listener the listener invoked for all the callbacks, this must
     * not be null.
     * @throws NullPointerException if {@code listener} is null.
     * @deprecated Use {@link #GestureDetector(android.content.Context,
     *      android.view.GestureDetector.OnGestureListener)} instead.
     */使用提供的侦听器创建GestureDetector。
      *你只能从UI线程使用这个构造函数(这是通常的情况)
      * @see android.os.Handler#Handler()
      *:
      * @param listener为所有回调调用的监听器,这必须
      *不能为null。
    @Deprecated
    public GestureDetector(OnGestureListener listener) {
        this(null, listener, null);
    }
/**
     * Creates a GestureDetector with the supplied listener.
     * You may only use this constructor from a {@link android.os.Looper} thread.
     * @see android.os.Handler#Handler()
     *
     * @param context the application's context
     * @param listener the listener invoked for all the callbacks, this must
     * not be null.
     * @throws NullPointerException if {@code listener} is null.
     */使用提供的侦听器创建GestureDetector。
      *你只能从{@link android.os.Looper}线程中使用这个构造函数。
      * @see android.os.Handler#Handler()
      *:
      * @param context应用程序的上下文
      * @param listener为所有回调调用的监听器,这必须
      *不能为null。
    public GestureDetector(Context context, OnGestureListener listener) {
        this(context, listener, null);
    }
/**
     * Creates a GestureDetector with the supplied listener that runs deferred events on the
     * thread associated with the supplied {@link android.os.Handler}.
     * @see android.os.Handler#Handler()
     *
     * @param context the application's context
     * @param listener the listener invoked for all the callbacks, this must
     * not be null.
     * @param handler the handler to use for running deferred listener events.
     *
     * @throws NullPointerException if {@code listener} is null.
     */使用提供的侦听器创建GestureDetector,在其上运行延迟事件
      *线程与提供的{@link android.os.Handler}相关联。
      * @see android.os.Handler#Handler()
      *:
      * @param context应用程序的上下文
      * @param listener为所有回调调用的监听器,这必须
      *不能为null。
      * @param handler用于运行延迟侦听器事件的处理程序。
    public GestureDetector(Context context, OnGestureListener listener, Handler handler) {}
/**
     * Creates a GestureDetector with the supplied listener that runs deferred events on the
     * thread associated with the supplied {@link android.os.Handler}.
     * @see android.os.Handler#Handler()
     *
     * @param context the application's context
     * @param listener the listener invoked for all the callbacks, this must
     * not be null.
     * @param handler the handler to use for running deferred listener events.
     * @param unused currently not used.
     *
     * @throws NullPointerException if {@code listener} is null.
     */使用提供的侦听器创建GestureDetector,在其上运行延迟事件
      *线程与提供的{@link android.os.Handler}相关联。
      * @see android.os.Handler#Handler()
      *:
      * @param context应用程序的上下文
      * @param listener为所有回调调用的监听器,这必须
      *不能为null。
      * @param handler用于运行延迟侦听器事件的处理程序。
      * @param unused当前未使用。
    public GestureDetector(Context context, OnGestureListener listener, Handler handler,
            boolean unused) {
        this(context, listener, handler);
    }
     一些公共方法:
/**
     * Sets the listener which will be called for double-tap and related
     * gestures.
     * 
     * @param onDoubleTapListener the listener invoked for all the callbacks, or
     *        null to stop listening for double-tap gestures.
     */设置将被双击并相关的监听器
      *手势。
      *:
      * @param onDoubleTapListener为所有回调调用的侦听器,或
      * null停止监听双击手势。
    public void setOnDoubleTapListener(OnDoubleTapListener onDoubleTapListener) {
        mDoubleTapListener = onDoubleTapListener;
    }
  /**
     * Sets the listener which will be called for context clicks.
     *
     * @param onContextClickListener the listener invoked for all the callbacks, or null to stop
     *            listening for context clicks.
     */设置将为上下文点击调用的侦听器。
      *:
      * @param onContextClickListener为所有回调调用的侦听器,或null停止
      *监听上下文点击。
    public void setContextClickListener(OnContextClickListener onContextClickListener) {
        mContextClickListener = onContextClickListener;
    }
/**
     * Set whether longpress is enabled, if this is enabled when a user
     * presses and holds down you get a longpress event and nothing further.
     * If it's disabled the user can press and hold down and then later
     * moved their finger and you will get scroll events. By default
     * longpress is enabled.
     *
     * @param isLongpressEnabled whether longpress should be enabled.
     */设置是否启用长按,如果在用户启用时启用
      *按下并按住,你得到一个longpress事件,没有进一步。
      *如果禁用,用户可以按住,然后稍后
      *移动他们的手指,你会得到滚动事件。 默认
      *启用长按。
      * @param isLongpressEnabled是否应启用longpress
    public void setIsLongpressEnabled(boolean isLongpressEnabled) {
        mIsLongpressEnabled = isLongpressEnabled;
    }


    /**
     * @return true if longpress is enabled, else false.
     */@return true如果长按启用,否则为false。
    public boolean isLongpressEnabled() {
        return mIsLongpressEnabled;
    }
    GestureDetector的一些简介就只有这么几个接口和方法,包括源码中继承Handler和onTouchEvent()方法,特别是onTouchEvent()方法,手势识别器就是依靠这个方法去实现一些操作。我简单的把手势识别器的用法写一下,也就是刚才源码帮我们实现3个接口的那个类。回到这个GestureDetector类的解释,首先要实例化,其次在View的onTouchEvent(MotionEvent)方法里确保调用(GestureDetector的)onTouchEvent(MotionEvent)方法。

 private GestureDetector detector;  //初始化
 private void initView(final Context context) {
        //2.实例化手势识别器
        detector = new GestureDetector(context,new GestureDetector.SimpleOnGestureListener()
{
            @Override
            public void onLongPress(MotionEvent e) {
                super.onLongPress(e);
                Toast.makeText(context,"长按",Toast.LENGTH_SHORT).show();
            }
            /**
             *
             * @param e1
             * @param e2
             * @param distanceX 在X轴滑动了的距离
             * @param distanceY 在Y轴滑动了的距离
             * @return
             */
            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                /**
                 *x:要在X轴移动的距离
                 *y:要在Y轴移动的距离
                 */
                scrollBy((int)distanceX,0);
                return true;
            }
            @Override
            public boolean onDoubleTap(MotionEvent e) {
                Toast.makeText(context,"双击",Toast.LENGTH_SHORT).show();
                return super.onDoubleTap(e);
            }
        }); //这里就是new的SimpleOnGestureListener类,还有很多方法这里只贴出了这几个。
@Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        //3.把事件传递给手势识别器
detector.onTouchEvent(event); //一定要传递进来,不然就没作用
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                System.out.println("onTouchEvent==ACTION_DOWN");
                break;
            case MotionEvent.ACTION_MOVE:
                System.out.println("onTouchEvent==ACTION_MOVE");
                break;
            case MotionEvent.ACTION_UP:
                System.out.println("onTouchEvent==ACTION_UP");
                break;
        }
        return true;
    }
      这就是GestureDetector手势识别器的简单用法,其它复杂化的就不写了。下面贴几个手势识别器的用法的网站,供大家参考!2016年就这样完了,明年继续奋斗。在技术的学习上就是要多花时间,认真认真再认真。我感觉csdn的编辑器不行啊,不知道是不是我没找到方法。
     http://www.cnblogs.com/transmuse/archive/2010/12/02/1894833.html
     http://blog.csdn.net/xyz_lmn/article/details/16826669
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值