Кнопка Android имеет вызов setOnTouchListener, но не переопределяет performClick

113

Когда я пытаюсь добавить onTouchListner()к кнопке, я получаю

Кнопка имеет вызов setOnTouchListener, но не отменяет 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, когда должно произойти действие щелчка.
kas
См. Мой ответ здесь: stackoverflow.com/questions/47170075/…
лямбда,

Ответы:

134

Это предупреждение появляется, потому что Android хочет напомнить вам подумать о слепых или слабовидящих людях, которые могут использовать ваше приложение. Я предлагаю вам посмотреть это видео, чтобы получить краткий обзор того, на что это похоже.

Все стандартные представления пользовательского интерфейса (например Button, TextViewи т. Д.) Настроены для предоставления слепым пользователям соответствующей обратной связи через службы доступности. Когда вы пытаетесь самостоятельно обрабатывать сенсорные события, вы рискуете забыть предоставить эту обратную связь. Это то, для чего нужно предупреждение.

Вариант 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, для которого вам нужны события касания. Если вы должны были сделать пользовательскую кнопку и называется performClick()в , onTouchEventкак я сделал выше для таможни 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;
        }
    });
}
Suragch
источник
1
Я использовал customviews из-за использования разных шрифтов. Поскольку теперь в Api 26 представлена ​​новая функция, шрифты в xml и для более старой версии используют библиотеку поддержки 26, которая поддерживает до Api 16. Поэтому я удалил все пользовательские представления. И появляется это глупое предупреждение, и решение состоит в том, чтобы снова создать некоторые из тех пользовательских представлений, для которых я использую setOnTouchListener. ха-ха-ха: D Так странно
Шан Сеши
19
Интересно, понимает ли Google, сколько часов разработчиков они тратят на это. Я имею в виду, они могли бы справиться с этим в api? тратить время на создание подклассов представлений или даже на поиск способов устранения его предупреждения, тратит много времени.
TatiOverflow 02
что, если вам нужен MotionEvent eventобъект в вашем doSomething()методе? Мне нужно проверить event.getY().
Матеус Гондим
@MateusGondim, я должен сказать, что я еще не очень компетентен в реализации performClick(). Моя первоначальная мысль: если event.getY()это не является неотъемлемой частью фактического события щелчка (то есть визуальных эффектов пользовательского интерфейса), то переместите эту логику обратно в onTouchEvent(). В противном случае вы можете создать переменную-член класса для хранения последнего Yзначения действия . Я также предлагаю вам ознакомиться с исходным кодом некоторых стандартных представлений, чтобы посмотреть, как это реализует Android. Мне нужно больше их изучить.
Suragch
1
@sisisisi, предупреждение появляется, когда вы отменяете, onTouchEvent()но нет performClick(). Это может включать в себя смахивание или щелчок или любое другое событие касания, которое вы пытаетесь зафиксировать.
Suragch
17

Решение:

  1. Создайте класс, расширяющий Button или любое другое представление, которое вы используете, и переопределите performClick ()

    class TouchableButton extends Button {
    
        @Override
        public boolean performClick() {
            // do what you want
            return true;
        }
    }
  2. Теперь используйте этот TouchableButton в xml и / или коде, и предупреждение исчезнет!

Sjd
источник
18
Это действительно мерзко. Нет возможности использовать существующие представления?
Milk
@Milk Нет. android.widget.Buttonжестко запрограммирован, поэтому он не позволяет вам этого делать. И похоже, что команда разработчиков Android сделала это намеренно.
tom_mai78101
11

Вы пробовали добавить:

view.performClick()

или добавив аннотацию suppresslint:

@SuppressLint("ClickableViewAccessibility")

?

лямбда
источник
2
Да. Эта Waring прибывает с версией android studio 3.0
kas
1
Хорошо, у меня есть альтернатива, чтобы исправить это предупреждение. см. stackoverflow.com/questions/47170075/…
лямбда,
1

Для настраиваемых элементов управления просмотром может потребоваться нестандартное поведение сенсорного события. Например, настраиваемый элемент управления может использовать метод прослушивания onTouchEvent (MotionEvent) для обнаружения событий ACTION_DOWN и ACTION_UP и запуска специального события щелчка. Для обеспечения совместимости со службами специальных возможностей код, обрабатывающий это настраиваемое событие щелчка, должен выполнять следующие действия:

Создайте соответствующий AccessibilityEvent для интерпретируемого действия щелчка. Включите службы специальных возможностей для выполнения настраиваемого действия щелчка для пользователей, которые не могут использовать сенсорный экран. Для эффективного выполнения этих требований ваш код должен переопределить метод performClick (), который должен вызывать суперреализацию этого метода, а затем выполнять любые действия, требуемые событием щелчка. Когда пользовательское действие щелчка обнаружено, этот код должен вызвать ваш метод performClick ().

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

ослеплять
источник