安卓OnTouchListener,onTouchEvent,onClickListener执行顺序

来源:互联网 发布:fifa online数据库 编辑:程序博客网 时间:2024/05/19 20:59

安卓控件有很多监听事件,比较典型的有OnTouchListener,onTouchEvent和mOnClickListener,来看下他们的执行顺序
我们先自定义一个Button,在他的onTouchEvent方法中加入log

@Override    public boolean onTouchEvent(MotionEvent event) {        Log.e("xw", "onTouchEvent");        return super.onTouchEvent(event);    }

放进布局后在Activity中设置回调

bt1.setOnTouchListener(new View.OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                Log.e("xw", "OnTouchListener");                return false;            }        });bt1.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Log.e("xw", "OnClickListener");            }        });

之后单击下,log信息为
这里写图片描述

可见是首先执行OnTouchListener,之后为onTouchEvent,最后才执行onClickListener内的方法,至于为什么OnTouchListener和onTouchEvent执行了两次,是因为在DOWN和UP时两个方法都被调用,至于onClickListener则只在UP的时候调用

我们看下安卓是怎么实现的

与事件分发相关联的三个方法分别为dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent,直接去看View的dispatchTouchEvent方法

public boolean dispatchTouchEvent(MotionEvent event) {        ......        ListenerInfo li = mListenerInfo;        if (li != null && li.mOnTouchListener != null                && (mViewFlags & ENABLED_MASK) == ENABLED                && li.mOnTouchListener.onTouch(this, event)) {            result = true;        }        if (!result && onTouchEvent(event)) {            result = true;        }        ......        return result;    }

我们先看ListenerInfo ,他是View的一个内部静态类

 static class ListenerInfo {        protected OnFocusChangeListener mOnFocusChangeListener;        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;        protected OnScrollChangeListener mOnScrollChangeListener;        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;        public OnClickListener mOnClickListener;        protected OnLongClickListener mOnLongClickListener;        protected OnContextClickListener mOnContextClickListener;        protected OnCreateContextMenuListener mOnCreateContextMenuListener;        ......    }

里面存储着View的各个Listener,我们之前设置的OnTouchListener也在其中

public void setOnTouchListener(OnTouchListener l) {        getListenerInfo().mOnTouchListener = l;    }ListenerInfo getListenerInfo() {        if (mListenerInfo != null) {            return mListenerInfo;        }        mListenerInfo = new ListenerInfo();        return mListenerInfo;    }

其他的像onClickListener也是这样存储

回来我们接着看dispatchTouchEvent方法,从上面我们可以知道如果有的话OnTouchListener是比onTouchEvent先执行的,当然前提是OnTouchListener返回false,即OnTouchListener并没有处理事件

接着调用onTouchEvent方法

public boolean onTouchEvent(MotionEvent event) {        ......        switch (action) {             case MotionEvent.ACTION_UP:                  ......                  performClick();                  ......                  break;        ......    }public boolean performClick() {        final boolean result;        final ListenerInfo li = mListenerInfo;        if (li != null && li.mOnClickListener != null) {            playSoundEffect(SoundEffectConstants.CLICK);            li.mOnClickListener.onClick(this);            result = true;        } else {            result = false;        }        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);        return result;    }

在View的onTouchEvent方法中,如果判断事件为MotionEvent.ACTION_UP时,则会调用performClick,而在performClick中则会回调mOnClickListener的onClick方法,即点击事件被回调,同时直接返回true

阅读全文
0 0
原创粉丝点击