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

时间:2014-12-13 18:54:50

标签: java android view

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

为什么我会收到警告?它背后的逻辑是什么,为什么它是好的 当您覆盖performClick

时,练习也会覆盖onTouchEvent

4 个答案:

答案 0 :(得分:50)

目的是什么?

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

世界上有数百万盲人。也许你通常不会想太多,但你应该。他们也使用Android。 “怎么样?”你可能会问。一个重要的方法是通过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>

请注意,我设置了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();
    }
}

注释

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

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

进一步研究

答案 1 :(得分: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;
 }

但这不是强制性的。因为我已经创建了一个自定义的knobView,它在我也面临这个警告的情况下工作得非常好。

答案 2 :(得分:6)

虽然这只是一个警告,可以忽略,但似乎是可访问性所必需的。

详细说明here

然后,当你管理一个动作时,你应该添加performClick,即:

    if (action == MotionEvent.ACTION_DOWN) {
        performClick(); // Call this method to handle the response, and
        // thereby enable accessibility services to
        // perform this action for a user who cannot
        // click the touchscreen.

答案 3 :(得分:2)

某些辅助功能服务未调用onTouchEvent,如点击&#34;更多...&#34;链接警告详情。

建议您覆盖performClick以执行所需操作,或至少将其覆盖在onTouchEvent旁边。

如果您的代码更适合触摸事件,您可以使用类似于:

的内容
@Override
public boolean performClick() {
    if (actionNotAlreadyExecuted) {
        MotionEvent myEvent = MotionEvent.obtain(long downTime, long eventTime, int action, float x, float y, int metaState);
        onTouch(myView, myEvent);
    }
    return true; // register it has been handled
}

有关通过代码访问触摸事件的更多信息,请访问trigger ontouch event programmatically