关于setOnTouchListener警告的消除

3,554 阅读2分钟

常常在为自定义组件或者View设置监听器的时候,会弹出类似于一下的警告:

Custom view view has setOnTouchListener called on it but does not override performClick

这是由于Touch监听器的执行顺序领先于Click监听器,并且当我们在Touch中消费掉事件后(即返回为true),Click监听器的对应方法就不会执行了。简单来说是:在onTouchEvent()方法中会执行PerformClick()方法,然后在PerformClick()方法中再去执行mOnClickListener监听器。

//第一部分
public boolean onTouchEvent(MotionEvent event) {
    //省略其他源码
    if (mPerformClick == null) {
        mPerformClick = new PerformClick();
    }
    if (!post(mPerformClick)) {
        performClickInternal();
    }
    //省略其他源码
    return false;
}

//第二部分
```
```
public boolean performClick() {
    // We still need to call this method to handle the cases where performClick() was called
    // externally, instead of through performClickInternal()
    notifyAutofillManagerOnClick();

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

如果我们旨在只针对Touch设置setOnTouchListener,那么系统就会警告我们,因为如果不做处理的情况下,会造成点击事件无法正常被监听到(如果有点击事件)。

常用的消除警告的方法有两种,第一种就是直接使用:

@SuppressLint("ClickableViewAccessibility")

但是这种方法依旧没有彻底解决问题,只是抑制了这种类型的警告

第二种就是针对自己设置的监听器事件本身进行设置,具体做法采用一个自定义View来举例说明

public class MyView extends View {

    public MyView(Context context) {
        super(context);
        init(context);
    }

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context){

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }

    @Override
    public boolean performClick() {
        super.performClick();
        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                return true;
            case MotionEvent.ACTION_UP:
                performClick();
                return true;
        }
        return false;
    }
}

只要重写performClick()和onTouchEvent()方法,使得再确定是点击事件的时候手动去执行一次performClick()就可以了。

参考:www.coder.work/article/459…