个人习惯在代码里面写OnTouchListener,而不喜欢写OnClickListener,这样就经常会遇到#onTouch should call View#performClick when a click is detected这个警告。
本人有点强迫症,不喜欢代码里面有任何警告或者什么的,之前一直是直接用@SuppressLint("ClickableViewAccessibility"),忽略这个警告。本着最好不要使用SuppressLint的想法,抽空查了下资料。
在View中找到onTouchEvent的源码,在ACTION_UP中可以找到这一段
if (mPerformClick == null) {
mPerformClick = new PerformClick();
}
if (!post(mPerformClick)) {
performClick();
}
继续查找PerformClick()和performClick()的源码
private final class PerformClick implements Runnable {
@Override
public void run() {
performClick();
}
}
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);
notifyEnterOrExitForAutoFillIfNeeded(true);
return result;
}
可以看到在onTouchEvent的ACTION_UP过程中启用了一个新的线程来调用performClick(),而performClick()的作用时调用你在setOnClickListener时设置的onClick()方法。
一般来说可以直接忽略警告,因为在重写了ontouch之后一般不会在写onclicklistener,但是如果想要在实现ontouch的时候也要实现onclicklistener,就需要在ACTION_UP的时候再写一个view.performclick();
button.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
button.performClick();
break;
}
return false;
}
});
详细的分析可以参考这篇:OnTouch关于performClick的Warning