[置顶] 详解android中OnClickListener监听

菜鸟上路,个人见解,有错误的地方请多指教

OnClickListener是安卓控件的一个点击监听事件   这个接口 包含一个方法 void onClick(View v)

进去看源码会比较神奇的发现  view中 

public void setOnClickListener(OnClickListener l) {
        if (!isClickable()) {
            setClickable(true);
        }
        getListenerInfo().mOnClickListener = l;
    }

这个方法只是把控件设置为可以点击以及把 监听给予ListenerInfo 

  ListenerInfo getListenerInfo() {
        if (mListenerInfo != null) {
            return mListenerInfo;
        }
        mListenerInfo = new ListenerInfo();
        return mListenerInfo;
    }

至于ListenerInfo 是view中的一个静态类 里面定义了view的监听 点击长按 等等

在设置监听的时候没有触发onClick这个方法  那么这个方法在哪里调用了呢?

不难找到 

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;
    }

if判断语句这个很简单  就不说了 if语句第一句是处理声音的  li.mOnClickListener.onClick(this) 这个就是处理onClick方法了 所以控件设置的onclick 返回的v即是它本身

然后performClick()的调用 会发现是在onTouchEvent中  这个方法可能都很熟悉 对的  就是手势的方法  既然手势触发的方法 那么就必须了解

dispatchTouchEvent了  这个方法首先你需要知道一点,只要你触摸到了任何一个控件,就一定会调用该控件的dispatchTouchEvent方法

这个方法里面有个代码很关键

if (li != null && li.mOnTouchListener != null
                    && (mViewFlags & ENABLED_MASK) == ENABLED
                    && li.mOnTouchListener.onTouch(this, event)) {
                result = true;
            }

当然其中控件都是ENABLED的 mOnTouchListener是控件setOnTouchListener需要实现的接口

此接口 有个boolean方法onTouch    再看上面的if语句  如果控件设置了setOnTouchListener 那么前面的条件都满足  重要的是最后一个条件

li.mOnTouchListener.onTouch(this, event)   即是看你处理的onTouch方法是不是为true  都满足的话 那么就不会执行下面的onTouchEvent方法了

到这里就已经很清楚了  onclick 方法 执行的过程是 dispatchTouchEvent -- onTouchEvent中的手势ACTION_UP  

下面写个列子

tv.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
Log.d("tv---onClick --", "执行");
}
});

tv.setOnTouchListener(new OnTouchListener() {

@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.d("tv---onTouch --event action", String.valueOf(event.getAction()));
return true;
}
});

OnTouch返回true的时候  onClick方法不会被调用 

这只是个单独的view 碰触的过程   至于viewpager嵌套viewpager  ScrollView与listView  这些即是ViewGroup事件分发 拦截 消费了 详情请看http://www.android100.org/html/201406/04/18048.html  写得真心不错



你可能感兴趣的:(安卓,onclick,onTouch)