Android 按钮调用了 setOnTouchListener 但没有覆盖 performClick

Android button has setOnTouchListener called on it but does not override performClick

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

Button has setOnTouchListener called on it but does not override performClick

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

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

错误:

Custom view has setOnTouchListener called on it but does not override performClick If a View that overrides onTouchEvent or uses an OnTouchListener does not also implement performClick and call it when clicks are detected, the View may not handle accessibility actions properly. Logic handling the click actions should ideally be placed in View#performClick as some accessibility services invoke performClick when a click action should occur.

您是否尝试添加:

view.performClick()

或添加 suppresslint 注释:

@SuppressLint("ClickableViewAccessibility")

?

解法:

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

    class TouchableButton extends Button {
    
        @Override
        public boolean performClick() {
            // do what you want
            return true;
        }
    }
    
  2. 现在在 xml and/or 代码中使用此 TouchableButton,警告将消失!

出现此警告是因为 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;
        }
    });
}

Custom view controls may require non-standard touch event behavior. For example, a custom control may use the onTouchEvent(MotionEvent) listener method to detect the ACTION_DOWN and ACTION_UP events and trigger a special click event. In order to maintain compatibility with accessibility services, the code that handles this custom click event must do the following:

Generate an appropriate AccessibilityEvent for the interpreted click action. Enable accessibility services to perform the custom click action for users who are not able to use a touch screen. To handle these requirements in an efficient way, your code should override the performClick() method, which must call the super implementation of this method and then execute whatever actions are required by the click event. When the custom click action is detected, that code should then call your performClick() method.

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

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

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