最近项目里面遇到了一个问题,我给一个子view设置了onClick事件,但是没有响应了。很普通的问题是吧,对的。很普通的问题,它就是没有响应了。
你一定会认为,我没有阅读这2篇博客,
http://blog.csdn.net/guolin_blog/article/details/9153747
http://blog.csdn.net/guolin_blog/article/details/9097463
事实上,我之前就看过了。 这里面一共涉及到了3个重要的方法,
1, dispatchTouchEvent(MotionEvent ev) ;
2,onInterceptTouchEvent(MotionEvent ev);
3, onTouchEvent(MotionEvent event)。
dispatchTouchEvent负责分发事件,onInterceptTouchEvent负责拦截事件,onTouchEvent负责处理(消耗)事件。
一开始,我认为所有的控件都可以重写这3个方法。 事实上不是的,继承自viewGroup的组件才同时有这3个方法,继承自view的组件只有1,3 这2个方法。
好了,好了,我们还是回到最前面的话题,为什么onClick事件没有响应了。我设置了监听,设置了视图可点击(看了源码才知道,不需要设置视图可点击,设置监听的时候,android系统会帮我们设置视图可点击)还是没有响应。
仔细检查代码,发现这个子View是一个自定义的view,里面重写了onTouchEvent(MotionEvent event),如下:
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!mRenderer.isLongClickEnabled()) {
if (mChart.getTouchedX() > -1) {
mChart.setTouchedX(-1);
}
return false;
}else{
final int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
// save the x and y so they can be used in the click and long press
// listeners
oldX = event.getX();
oldY = event.getY();
mLastMotionX = mInitialMotionX = event.getX();
mLastMotionY = mInitialMotionY = event.getY();
mIsCancelLongClick = false;
mIsStartLongClick = false;
if (mTapTask != null) {
mTapTask.cancel();
}
mTimer.schedule(mTapTask = new TapTask(), 200);
} else if (action == MotionEvent.ACTION_MOVE) {
mLastMotionX = event.getX();
mLastMotionY = event.getY();
if (mIsStartLongClick) {
mChart.setTouchedX(mLastMotionX);
repaint();
}
} else if (action == MotionEvent.ACTION_CANCEL
|| action == MotionEvent.ACTION_UP) {
mIsCancelLongClick = true;
mChart.setTouchedX(-1);
repaint();
}
return true;
}
}
我知道没人会仔细看我的源码,我简单说一下,第一个判断,是说这个视图是否处于长按模式,如果不是,返回false,表示不处理点击事件。
最后,不管怎么样都会返回true,表示处于长按模式,要处理长按事件。
于是,我心里想,是不是我没有设置长按模式,所以才办法响应click,于是...然后,你们懂的,失败。接着,我想,是不是要把第一个if之后的返回改为真,于是...然后,你们懂的,失败。
然后,我再次仔细的看了原作者的文章,突然有一句话提醒了我:
“而上面的分析还透漏出了一个重要的信息,那就是onClick的调用肯定是在onTouchEvent(event)方法中的!那我们马上来看下onTouchEvent的源码,”。
onclick的响应是在view的onTouchEvent(event)方法处理的,这里我都没有调用父类的onTouchEvent(event),它怎么响应onclick,于是,将return false改为super.onTouchEvent(event),然后,成功,在非长按模式下,完美响应onclick事件。
所以,大家在发现onclick事件没有响应的时候,一定要记得去view的onTouchEvent(event)方法里面去检查一遍,是否有调用super.onTouchEvent(event)。当然了,你也是需要去检查ontouch()的返回值,检查父类的
dispatchTouchEvent(MotionEvent ev) 和onInterceptTouchEvent(MotionEvent ev)方法