【问题标题】:Android button has setOnTouchListener called on it but does not override performClickAndroid 按钮调用了 setOnTouchListener 但不覆盖 performClick
【发布时间】:2017-11-04 03:34:50
【问题描述】:

当我尝试将onTouchListner() 添加到一个按钮时,它让我得到了

按钮调用了 setOnTouchListener 但没有覆盖 执行点击

警告。有人知道怎么解决吗?

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

错误:

自定义视图调用了 setOnTouchListener 但没有覆盖 performClick 如果 View 覆盖 onTouchEvent 或使用 OnTouchListener 也没有实现 performClick 并在什么时候调用它 检测到点击,视图可能无法处理可访问性操作 适当地。理想情况下,处理点击动作的逻辑应该放在 View#performClick 作为一些无障碍服务调用 performClick 什么时候应该发生点击动作。

【问题讨论】:

  • 自定义视图 ImageView 已调用 setOnTouchListener 但未覆盖 performClick 如果覆盖 onTouchEvent 或使用 OnTouchListener 的视图也未实现 performClick 并在检测到点击时调用它,则该视图可能不会正确处理可访问性操作。理想情况下,处理点击动作的逻辑应该放在 View#performClick 中,因为一些无障碍服务会在点击动作发生时调用 performClick。
  • 请在此处查看我的答案:stackoverflow.com/questions/47170075/…

标签: android ontouchlistener


【解决方案1】:

出现此警告是因为 Android 想要提醒您考虑可能正在使用您的应用的盲人或视障人士。我建议您观看this video 以快速了解情况。

标准 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"/>

有关制作自定义视图的更多详细信息,请参阅my other answer

选项 2:消除警告

其他时候最好让警告静音。例如,我不确定您想对需要触摸事件的Button 做什么。如果您要创建一个自定义按钮并在onTouchEvent 中调用performClick(),就像我在上面为自定义TextView 所做的那样,那么它每次都会被调用两次,因为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;
        }
    });
}

【讨论】:

  • 我使用的是自定义视图,因为使用了不同的字体。现在在 Api 26 中引入了新功能,xml 中的字体和旧版本使用支持库 26,它支持到 Api 16。所以我删除了所有自定义视图。这个愚蠢的警告出现了,解决方案是再次创建一些我正在使用 setOnTouchListener 的自定义视图。哈哈哈:D好奇怪
  • 我想知道谷歌是否意识到他们为此浪费了多少开发人员的时间。我的意思是,他们也许可以在 api 中处理这个问题?花时间子类化视图甚至搜索如何解决他的警告会浪费大量时间。
  • 如果您的doSomething() 方法中需要MotionEvent event 对象怎么办?我需要检查event.getY()
  • @sisisisi,当您覆盖 onTouchEvent() 而不是 performClick() 时会出现警告。这可能包括滑动或单击或您尝试捕获的任何其他触摸事件。
  • 有时该应用程序不适合盲人。这很可悲,但这就是生活。
【解决方案2】:

解决方案:

  1. 创建一个扩展 Button 或您正在使用的任何视图的类并覆盖 performClick()

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

【讨论】:

  • 这真的很恶心。有没有办法使用现有的视图?
  • @Milk 不。 android.widget.Button 是硬编码的,所以它不允许你这样做。这似乎是 Android 开发团队有意为之。
  • 你需要添加'''super.performClick();
【解决方案3】:

您是否尝试过添加:

view.performClick()

或添加抑制注释:

@SuppressLint("ClickableViewAccessibility")

?

【讨论】:

【解决方案4】:

自定义视图控件可能需要非标准的触摸事件行为。 例如,自定义控件可以使用 onTouchEvent(MotionEvent) 侦听器方法来检测 ACTION_DOWN 和 ACTION_UP 事件和 触发特殊的点击事件。为了保持兼容性 无障碍服务,处理此自定义点击事件的代码 必须执行以下操作:

为解释的点击生成一个适当的 AccessibilityEvent 行动。启用无障碍服务以执行自定义点击 无法使用触摸屏的用户的操作。处理 这些要求以一种有效的方式,你的代码应该覆盖 performClick() 方法,该方法必须调用的超级实现 此方法,然后执行所需的任何操作 点击事件。当检测到自定义点击操作时,该代码 然后应该调用您的 performClick() 方法。

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

【讨论】:

    【解决方案5】:

    在被覆盖的 OnTouchListener 中,您将 MotionEvent 解释为单击,调用 view.performClick();(这将调用 onClick())。

    它是给用户反馈,例如。以点击声音的形式。

    【讨论】:

      猜你喜欢
      • 2023-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-12
      相关资源
      最近更新 更多