自定义视图 ...覆盖 onTouchEvent 但不执行单击目的是什么?如何覆盖performClick() 法典进一步研究

我在我正在开发的自定义Android视图中收到此警告(来自问题标题)。

为什么我会收到警告?它背后的逻辑是什么,即为什么在覆盖时也覆盖是一种很好
的做法?performClickonTouchEvent


答案 1

目的是什么?

在其他一些答案中,您可以看到使警告消失的方法,但重要的是要了解为什么系统首先希望您覆盖。performClick()

世界上有数以百万计的盲人。也许你通常不会过多地考虑它们,但你应该这样做。他们也使用Android。“怎么样?”你可能会问。一个重要的方法是通过TalkBack应用程序。它是一个提供音频反馈的屏幕阅读器。您可以通过转到TalkBack>“设置”>“辅助功能”在手机中将其打开。请在此处完成教程。这真的很有趣。现在尝试闭上眼睛使用您的应用程序。你可能会发现你的应用程序充其量非常烦人,最坏的情况是完全破碎的。这对你来说是一个失败,任何有视力障碍的人都会快速卸载。

观看Google的这个精彩视频,了解如何使您的应用程序可访问。

如何覆盖performClick()

让我们看一个示例自定义视图,了解重写的实际工作原理。我们将制作一个简单的导弹发射应用程序。自定义视图将是触发它的按钮。performClick()

enter image description here

启用TalkBack后听起来要好得多,但是动画GIF不允许音频,因此您只需要自己尝试一下即可。

法典

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <net.example.customviewaccessibility.CustomView
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:contentDescription="Activate missile launch"
        android:layout_centerInParent="true"
        />

</RelativeLayout>

请注意,我设置了 .这允许 TalkBack 在用户感觉到自定义视图时读出自定义视图是什么。contentDescription

自定义视图.java

public class CustomView extends View {

    private final static int NORMAL_COLOR = Color.BLUE;
    private final static int PRESSED_COLOR = Color.RED;

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

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

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

    private void init() {
        setBackgroundColor(NORMAL_COLOR);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                setBackgroundColor(PRESSED_COLOR);
                return true;

            case MotionEvent.ACTION_UP:
                setBackgroundColor(NORMAL_COLOR);

                // For this particular app we want the main work to happen
                // on ACTION_UP rather than ACTION_DOWN. So this is where
                // we will call performClick(). 
                performClick();
                return true;
        }
        return false;
    }

    // Because we call this from onTouchEvent, this code will be executed for both
    // normal touch events and for when the system calls this using Accessibility 
    @Override
    public boolean performClick() {
        super.performClick();

        launchMissile();

        return true;
    }

    private void launchMissile() {
        Toast.makeText(getContext(), "Missile launched", Toast.LENGTH_SHORT).show();
    }
}

笔记

  • 该文档还使用了一个变量,该变量似乎用于过滤掉额外的修饰事件,但由于它对于我们的应用程序没有很好的解释或严格必要,所以我省略了它。如果你做了一个真正的导弹发射器应用程序,我建议你更多地研究这个问题。mDownTouch
  • 发射导弹的主要方法()只是从 中调用。请注意,如果您也有它,请不要调用它两次。您需要根据自定义视图的具体情况,准确决定如何以及何时调用业务逻辑方法。launchMissile()performClick()onTouchEvent
  • 不要覆盖然后不做任何事情只是为了摆脱警告。如果你想忽略世界上数以百万计的盲人,那么你可以压制警告。至少这样,你对自己的无情是诚实的。performClick()

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) { ... }
    

进一步研究


答案 2

此警告告诉您覆盖performClick

@Override
 public boolean performClick() {
  // Calls the super implementation, which generates an AccessibilityEvent
        // and calls the onClick() listener on the view, if any
        super.performClick();

        // Handle the action for the custom click here

        return true;
 }

但这不是强制性的。由于我已经创建了一个自定义的knobView,并且它工作得很好,我也面临着这个警告。


推荐