Przycisk systemu Android wywołał setOnTouchListener, ale nie przesłania performClick


113

Kiedy próbuję dodać onTouchListner()do przycisku, pojawia się plik

Button wywołał setOnTouchListener, ale nie przesłania performClick

ostrzeżenie. Czy ktoś wie jak to naprawić?

1

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

Błąd:

Widok niestandardowy wywołał na nim funkcję setOnTouchListener, ale nie przesłania performClick Jeśli widok, który przesłania onTouchEvent lub używa OnTouchListener, nie implementuje również performClick i wywołuje go po wykryciu kliknięć, widok może nie obsługiwać poprawnie działań związanych z ułatwieniami dostępu. Logika obsługująca akcje kliknięcia powinna być idealnie umieszczona w widoku # performClick, ponieważ niektóre usługi ułatwień dostępu wywołują performClick, gdy powinno nastąpić kliknięcie.


Widok niestandardowy ImageViewwywołał na nim funkcję setOnTouchListener, ale nie przesłania performClick Jeśli widok, który przesłania onTouchEvent lub używa OnTouchListener, nie implementuje również performClick i wywołuje go po wykryciu kliknięć, widok może nie obsługiwać poprawnie działań związanych z ułatwieniami dostępu. Logika obsługująca akcje kliknięcia powinna być idealnie umieszczona w widoku # performClick, ponieważ niektóre usługi ułatwień dostępu wywołują performClick, gdy powinno nastąpić kliknięcie.
kasie

Zobacz moją odpowiedź tutaj: stackoverflow.com/questions/47170075/…
lambda

Odpowiedzi:


134

To ostrzeżenie pojawia się, ponieważ Android chce przypomnieć Ci o osobach niewidomych lub niedowidzących, które mogą używać Twojej aplikacji. Proponuję obejrzeć ten film, aby uzyskać szybki przegląd tego, jak to jest.

Standardowe widoki UI (jak Button, TextViewetc.) są ustanowione, aby zapewnić użytkownikom ciemnej z odpowiedniej informacji zwrotnej za pośrednictwem usług dostępu. Kiedy próbujesz samodzielnie poradzić sobie ze zdarzeniami dotykowymi, istnieje ryzyko, że zapomnisz przekazać tę informację zwrotną. Po to jest ostrzeżenie.

Opcja 1: utwórz widok niestandardowy

Obsługa zdarzeń dotykowych jest zwykle wykonywana w widoku niestandardowym. Nie odrzucaj tej opcji zbyt szybko. To naprawdę nie jest takie trudne. Oto pełny przykład a, TextViewktóry jest zastępowany w celu obsługi zdarzeń dotykowych:

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

Wtedy użyjesz go w ten sposób:

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

Zobacz moją drugą odpowiedź, aby uzyskać więcej informacji na temat tworzenia niestandardowego widoku.

Opcja 2: wyciszenie ostrzeżenia

Innym razem lepiej po prostu wyciszyć ostrzeżenie. Na przykład nie jestem pewien, co chcesz zrobić z Buttonwydarzeniami dotykowymi, do których potrzebujesz. Jeśli było zrobić przycisk niestandardowy i nazywa performClick()się onTouchEventtak jak ja powyżej dla zwyczaju TextView, to byłoby uzyskać wywołana dwukrotnie za każdym razem, bo Buttonjuż nazywa performClick().

Oto kilka powodów, dla których warto po prostu wyciszyć ostrzeżenie:

  • Praca, którą wykonujesz ze zdarzeniem dotykowym, jest tylko wizualna. Nie ma to wpływu na rzeczywiste działanie Twojej aplikacji.
  • Masz zimne serce i nie zależy ci na tym, by uczynić świat lepszym miejscem dla niewidomych.
  • Jesteś zbyt leniwy, aby skopiować i wkleić kod, który podałem w opcji 1 powyżej.

Dodaj następujący wiersz na początku metody, aby pominąć ostrzeżenie:

@SuppressLint("ClickableViewAccessibility")

Na przykład:

@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
Używałem customviews ze względu na różne czcionki. Ponieważ teraz w Api 26 wprowadzono nową funkcję, czcionki w xml i dla starszych wersji używają biblioteki obsługi 26, która obsługuje do Api 16. Dlatego usunąłem wszystkie niestandardowe widoki. I pojawia się to głupie ostrzeżenie i rozwiązaniem jest ponowne utworzenie niektórych niestandardowych widoków, dla których używam setOnTouchListener. hahaha: D Tak dziwne
Shan Xeeshi

19
Zastanawiam się, czy Google zdaje sobie sprawę, ile godzin programistów marnują przez to. Chodzi mi o to, że mogliby sobie z tym poradzić w ramach interfejsu API? spędzanie czasu na podklasowaniu widoków lub nawet szukaniu sposobów rozwiązania problemu z jego ostrzeżeniem marnuje wiele godzin.
TatiOverflow

co jeśli potrzebujesz MotionEvent eventobiektu w swojej doSomething()metodzie? Muszę sprawdzić event.getY().
Mateus Gondim

@MateusGondim, muszę powiedzieć, że nadal nie jestem zbyt kompetentny we wdrażaniu performClick(). Moja początkowa myśl jest taka, że ​​jeśli event.getY()nie jest integralną częścią rzeczywistego zdarzenia kliknięcia (tj. Wizualnych efektów interfejsu użytkownika), przenieś tę logikę z powrotem do onTouchEvent(). W przeciwnym razie możesz utworzyć zmienną składową klasy, aby przechowywać ostatnią Ywartość akcji . Sugeruję również sprawdzenie kodu źródłowego kilku standardowych widoków, więc zobacz, jak implementuje go Android. Sam muszę je lepiej przestudiować.
Suragch

1
@sisisisi, ostrzeżenie pojawia się, gdy nadpisujesz, onTouchEvent()ale nie performClick(). Może to obejmować przesunięcie, kliknięcie lub inne zdarzenie dotykowe, które próbujesz uchwycić.
Suragch

17

Rozwiązanie:

  1. Utwórz klasę, która rozszerza Button lub inny widok, którego używasz, i nadpisz performClick ()

    class TouchableButton extends Button {
    
        @Override
        public boolean performClick() {
            // do what you want
            return true;
        }
    }
  2. Teraz użyj tego TouchableButton w XML i / lub kodzie, a ostrzeżenie zniknie!


18
To jest naprawdę obrzydliwe. Czy nie ma możliwości wykorzystania istniejących widoków?
Milk

@Milk Nope. android.widget.Buttonjest zakodowane na stałe, więc nie pozwala na to. Wydaje się, że jest to bardzo zamierzone ze strony zespołu programistów Androida.
tom_mai78101


1

Niestandardowe kontrolki widoku mogą wymagać niestandardowego zachowania zdarzeń dotykowych. Na przykład kontrolka niestandardowa może używać metody nasłuchiwania onTouchEvent (MotionEvent) do wykrywania zdarzeń ACTION_DOWN i ACTION_UP i wyzwalania specjalnego zdarzenia kliknięcia. Aby zachować zgodność z usługami ułatwień dostępu, kod obsługujący to zdarzenie kliknięcia niestandardowego musi wykonywać następujące czynności:

Wygeneruj odpowiednie zdarzenie AccessibilityEvent dla interpretowanej akcji kliknięcia. Włącz usługi ułatwień dostępu, aby wykonać niestandardową akcję kliknięcia dla użytkowników, którzy nie mogą używać ekranu dotykowego. Aby efektywnie obsłużyć te wymagania, Twój kod powinien przesłonić metodę performClick (), która musi wywołać super implementację tej metody, a następnie wykonać wszelkie czynności wymagane przez zdarzenie click. Po wykryciu niestandardowej akcji kliknięcia ten kod powinien wywołać metodę performClick ().

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.