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

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

问题描述

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

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

解决方案

目的是什么?

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

世界上有数百万盲人.也许您通常不会考虑太多,但您应该考虑.他们也使用安卓.如何?"你可能会问.一种重要的方式是通过 也使用一个 mDownTouch 变量,它似乎用于过滤掉额外的修饰事件,但由于它没有得到很好的解释或对我们的应用程序来说是绝对必要的,所以我把它省略了.如果您制作的是真正的导弹发射器应用,我建议您多研究一下.

  • 发射导弹的主要方法 (launchMissile()) 只是从 performClick() 调用.如果 onTouchEvent 中也有它,请注意不要调用它两次.您需要根据自定义视图的具体情况准确决定调用业务逻辑方法的方式和时间.
  • 不要覆盖 performClick() 然后什么都不做只是为了摆脱警告.如果你想忽略世界上数以百万计的盲人,那么你可以压制警告.至少这样你才能坦诚面对自己的无情.

    @SuppressLint("ClickableViewAccessibility")@覆盖公共布尔 onTouchEvent(MotionEvent 事件) { ... }

  • 进一步研究

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

    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?

    解决方案

    What's the purpose?

    In some of the other answers you can see ways to make the warning go away, but it is important to understand why the system wants you to override performClick() in the first place.

    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.

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

    How to override 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.

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

    Code

    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>
    

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

    Notes

    • 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) { ... }
      

    Further study

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

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