Android按钮已经调用了setOnTouchListener,但没有覆盖performClick方法

185

当我尝试将 onTouchListner() 添加到按钮上时,它会提示

Button has setOnTouchListener called on it but does not override performClick

警告。有人知道如何解决吗?

1

btnleftclick.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent motionEvent) {
        return false;
    }
});

错误:

自定义视图在其上调用了setOnTouchListener,但没有重写performClick。如果覆盖onTouchEvent或使用OnTouchListener的视图不实现performClick并在检测到点击时调用它,则该视图可能无法正确处理辅助功能操作。理想情况下,应将处理单击操作的逻辑放置在View#performClick中,因为一些辅助功能服务在应发生单击操作时调用performClick。


自定义视图ImageView已经设置了setOnTouchListener,但没有重写performClick。如果一个视图重写了onTouchEvent或使用了OnTouchListener,但在检测到点击时没有实现performClick并调用它,则该视图可能无法正确处理可访问性操作。理想情况下,应该将处理点击操作的逻辑放置在View#performClick中,因为一些可访问性服务在需要进行点击操作时会调用performClick - Garry
请查看我的答案:https://dev59.com/vlYN5IYBdhLWcg3wm5Oi#47170922 - lambda
6个回答

234

这个警告出现是因为Android想提醒您考虑到使用您的应用程序的盲人或视觉受损人士。我建议您观看这个视频,快速了解一下相关情况。

标准UI视图(如ButtonTextView等)都已设置好,通过辅助功能服务为盲人用户提供适当的反馈。如果您尝试自己处理触摸事件,则有可能会忘记提供该反馈。这就是这个警告的作用。

选项1:创建自定义视图

处理触摸事件通常是在自定义视图中完成的。不要太快地否认这个选项,它其实并不难。以下是一个完整的示例,将 TextView 覆盖以处理触摸事件:

public class CustomTextView extends AppCompatTextView {

    public CustomTextView(Context context) {
        super(context);
    }

    public CustomTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

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

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

            case MotionEvent.ACTION_UP:
                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();
        doSomething();
        return true;
    }

    private void doSomething() {
        Toast.makeText(getContext(), "did something", Toast.LENGTH_SHORT).show();
    }
}

然后你只需要像这样使用它:

<com.example.myapp.CustomTextView
    android:id="@+id/textview"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="20dp"
    android:text="Click me to do something"/>

查看我的另一个答案,以获取有关创建自定义视图的更多详细信息。

选项2:消除警告

其他时候,只需消除警告可能更好。例如,我不确定您想要使用触摸事件做什么 Button。如果您制作了自定义按钮并在onTouchEvent中像我上面为自定义 TextView所做的那样调用了performClick(),那么每次都会被调用两次,因为Button已经调用了performClick()

以下是您可能希望仅消除警告的几个原因:

  • 您使用触摸事件进行的工作仅具有视觉效果。它不会影响您的应用程序的实际工作。
  • 您冷酷无情,不关心为盲人创造更美好的世界。
  • 您太懒了,不想复制和粘贴我在上面提供的选项1中的代码。

将以下行添加到该方法的开头以抑制警告:

@SuppressLint("ClickableViewAccessibility")
例如:
@SuppressLint("ClickableViewAccessibility")
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Button myButton = findViewById(R.id.my_button);
    myButton.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            return false;
        }
    });
}

1
我曾经使用自定义视图是因为我在使用不同的字体。现在,Api 26引入了新特性——在xml中使用字体,而对于旧版则需要使用支持库26,该库支持Api 16。所以我删除了所有自定义视图。但这个愚蠢的警告出现了,解决方法是要重新创建一些需要使用setOnTouchListener的自定义视图。哈哈哈 :D 如此奇怪。 - Zeeshan
81
我想知道谷歌是否意识到了他们浪费了多少开发人员的时间。我的意思是,他们或许可以在API内解决这个问题?花费时间去子类化视图或者甚至搜索如何解决警告信息,都浪费了很多时间。 - TatiOverflow
如果我理解正确的话,当在检测滑动而不是点击时出现此警告时,如果我能通过辅助功能以某种方式检测到ACTION_DOWN,那么除了抑制之外,我只能对其进行其他操作,对吗? - sisisisi
1
@sisisisi,当您重写onTouchEvent()而不是performClick()时会出现警告。这可能包括您尝试捕获的滑动或单击或任何其他触摸事件。 - Suragch
5
有时应用程序并非面向盲人设计,这很悲哀,但这就是生活。 - Cequiel
显示剩余4条评论

17

解决方案:

  1. 创建一个继承自Button或其他视图的类,并重写performClick()方法。

class TouchableButton extends Button {

    @Override
    public boolean performClick() {
        // do what you want
        return true;
    }
}
现在在XML和/或代码中使用这个TouchableButton,警告将会消失!

33
这真的很恶心。有没有办法使用现有的观点? - Milk
@Milk 不行。android.widget.Button 是硬编码的,所以不允许你这样做。而且这似乎是 Android 开发团队的有意为之。 - tom_mai78101
你需要添加 '''super.performClick();''' - Miguel Tomás

12

你尝试过添加冒号“:”吗?

view.performClick()

或者添加 suppresslint 注释:

@SuppressLint("ClickableViewAccessibility")

?


4
是的。这个警告是在Android Studio 3.0版本中出现的。 - Garry
1
好的,我有一个替代方案来解决那个警告。请参见:https://dev59.com/vlYN5IYBdhLWcg3wm5Oi - lambda

1
自定义视图控件可能需要非标准的触摸事件行为。例如,自定义控件可能使用onTouchEvent(MotionEvent)监听器方法来检测ACTION_DOWN和ACTION_UP事件并触发特殊的点击事件。为了保持与辅助功能服务的兼容性,处理此自定义点击事件的代码必须执行以下操作: 为解释的点击动作生成适当的AccessibilityEvent。使辅助功能服务能够为无法使用触摸屏幕的用户执行自定义单击操作。为了以高效的方式处理这些要求,您的代码应该重写performClick()方法,这个方法必须调用super实现并执行单击事件所需的任何操作。当检测到自定义单击动作时,那段代码应该调用您的performClick()方法。

https://developer.android.com/guide/topics/ui/accessibility/custom-views#custom-touch-events


0

你可以抑制一个警告

@SuppressLint("ClickableViewAccessibility")

或者调用performClick()

[示例]


0
在重写的OnTouchListener中,当您将MotionEvent解释为单击时,请调用view.performClick();(这将调用onClick())。
这是为了给用户反馈,例如以点击声的形式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接