自定义视图...覆盖onTouchEvent但不执行performClick

pet*_*rov 47 java android android-custom-view android-view

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

为什么我会收到警告?它背后的逻辑是什么,即为什么在
覆盖performClick时也会覆盖它onTouchEvent

Sur*_*gch 62

目的是什么?

在其他一些答案中,您可以看到使警告消失的方法,但重要的是要了解系统首先要求您覆盖的原因performClick().

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

观看Google的精彩视频,了解如何使您的应用易于访问.

如何覆盖 performClick()

让我们看一个示例自定义视图,看看覆盖performClick()实际上是如何工作的.我们将制作一个简单的导弹发射应用程序.自定义视图将是触发它的按钮.

在此输入图像描述

启用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>
Run Code Online (Sandbox Code Playgroud)

请注意,我设置了contentDescription.这允许TalkBack读出当用户感觉到自定义视图时的自定义视图.

CustomView.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();
    }
}
Run Code Online (Sandbox Code Playgroud)

笔记

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

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) { ... }
    
    Run Code Online (Sandbox Code Playgroud)

进一步研究


Xar*_*mer 16

此警告告诉您覆盖 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;
 }
Run Code Online (Sandbox Code Playgroud)

但这不是强制性的.因为我已经创建了一个自定义knobView,它在我也面临这个警告的地方工作得很好.

  • 关键是你只有评论"处理自定义单击此处的操作"的部分.我该怎么处理?我认为没有什么用处.我不想写出无用的代码只是tutsut Lint. (7认同)