自定义视图...覆盖onTouchEvent,但不覆盖performClick [英] Custom view ... overrides onTouchEvent but not performClick

查看:615
本文介绍了自定义视图...覆盖onTouchEvent,但不覆盖performClick的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I get this warning (from the question title) in a custom Android view I am developing.

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

Why do I get warned? What's the logic behind it i.e. why is it a good
practice to also override performClick when you override onTouchEvent?

推荐答案

目的是什么?

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

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

There are millions of blind people in the world. Maybe you don't normally think about them much, but you should. They use Android, too. "How?" you might ask. One important way is through the TalkBack app. It is a screen reader that gives audio feedback. You can turn it on in your phone by going to Settings > Accessibility > TalkBack. Go through the tutorial there. It is really interesting. Now try to use your app with your eyes closed. You'll probably find that your app is extremely annoying at best and completely broken at worst. That's a fail for you and a quick uninstall by anyone's who's visually impaired.

观看Google播放的精彩视频,以介绍如何使您的应用可访问.

Watch this excellent video by Google for an introduction into making your app accessible.

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

Let's look at a example custom view to see how overriding performClick() actually works. We'll make a simple missile launching app. The custom view will be the button to fire it.

启用话语提示"后听起来要好得多,但是动画gif不允许音频,因此您只需要自己尝试一下即可.

It sounds a lot better with TalkBack enabled, but animated gifs don't allow audio, so you will just have to try it yourself.

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.这样,当用户感觉到自定义视图时,话语提示"便可以读出该视图.

Notice that I set the contentDescription. This allows TalkBack to read out what the custom view is when the user feels over it.

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();
    }
}

注释

  • 文档也使用一个mDownTouch变量,该变量似乎用于过滤掉额外的修饰事件,但是由于对我们的应用程序没有很好的解释或严格要求,因此我将其省略.如果您制作了真正的导弹发射器应用程序,建议您对此进行更多研究.
  • 发射导弹(launchMissile())的主要方法只是从performClick()中调用.如果在onTouchEvent中也有两次调用,请注意不要两次调用.您将需要根据自定义视图的具体情况,准确决定如何以及何时调用业务逻辑方法.
  • 请勿覆盖performClick(),然后对其进行任何操作只是为了摆脱警告.如果您想忽略世界上数百万的盲人,则可以取消警告.至少以这种方式,您对自己的无情感到诚实.

  • The documentation also uses an mDownTouch variable which appears to be used to filter out extra touch up events, but since it isn't well explained or strictly necessary for our app, I left it out. If you make a real missile launcher app, I suggest you look more into this.
  • The primary method that launches the missile (launchMissile()) is just called from performClick(). Be careful not to call it twice if you also have it in onTouchEvent. You will need to decide exactly how and when to call your business logic method depending on the specifics of your custom view.
  • Don't override performClick() and then do nothing with it just to get rid of the warning. If you want to ignore the millions of blind people in the world, then you can suppress the warning. At least that way you are honest about your heartlessness.

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

  • Accessibility overview
  • Build accessible custom views (especially the Handle custom touch events section)
  • Make apps more accessible

这篇关于自定义视图...覆盖onTouchEvent,但不覆盖performClick的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆