Il pulsante Android ha richiamato setOnTouchListener ma non sostituisce performClick


113

Quando provo ad aggiungere onTouchListner()a un pulsante, viene visualizzato il file

Il pulsante ha chiamato setOnTouchListener ma non sovrascrive performClick

avvertimento. Qualcuno sa come aggiustarlo?

1

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

Errore:

La visualizzazione personalizzata ha impostato setOnTouchListener ma non sostituisce performClick Se una visualizzazione che sostituisce onTouchEvent o utilizza un OnTouchListener non implementa anche performClick e la chiama quando vengono rilevati clic, la visualizzazione potrebbe non gestire correttamente le azioni di accessibilità. La logica che gestisce le azioni di clic dovrebbe idealmente essere collocata in Visualizza # performClick poiché alcuni servizi di accessibilità invocano performClick quando dovrebbe verificarsi un'azione di clic.


La visualizzazione personalizzata ImageViewha impostato setOnTouchListener ma non sostituisce performClick Se una visualizzazione che sostituisce onTouchEvent o utilizza un OnTouchListener non implementa anche performClick e la chiama quando vengono rilevati clic, la visualizzazione potrebbe non gestire correttamente le azioni di accessibilità. La logica che gestisce le azioni di clic dovrebbe idealmente essere collocata in Visualizza # performClick poiché alcuni servizi di accessibilità richiamano performClick quando dovrebbe verificarsi un'azione di clic.
Kas

Si prega di consultare la mia risposta qui: stackoverflow.com/questions/47170075/…
lambda

Risposte:


134

Questo avviso viene visualizzato perché Android vuole ricordarti di pensare alle persone non vedenti o ipovedenti che potrebbero utilizzare la tua app. Ti suggerisco di guardare questo video per una rapida panoramica di com'è.

Le visualizzazioni dell'interfaccia utente standard (come Button, TextViewecc.) Sono tutte impostate per fornire agli utenti non vedenti un feedback appropriato attraverso i servizi di accessibilità. Quando provi a gestire tu stesso gli eventi tattili, rischi di dimenticarti di fornire quel feedback. A questo serve l'avvertimento.

Opzione 1: crea una visualizzazione personalizzata

La gestione degli eventi di tocco è normalmente qualcosa che viene eseguito in una visualizzazione personalizzata. Non ignorare questa opzione troppo rapidamente. Non è poi così difficile. Ecco un esempio completo di un TextViewche viene sovrascritto per gestire gli eventi di tocco:

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

Quindi lo useresti in questo modo:

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

Vedi la mia altra risposta per maggiori dettagli sulla creazione di una visualizzazione personalizzata.

Opzione 2: silenziare l'avviso

Altre volte potrebbe essere meglio silenziare l'avvertimento. Ad esempio, non sono sicuro di cosa vuoi fare con un Buttonevento per il quale hai bisogno di eventi di tocco. Se si dovesse fare un pulsante personalizzato e chiamato performClick()a onTouchEventcome ho fatto in precedenza per il costume TextView, allora sarebbe ottenere chiamato due volte ogni volta perché Buttongià le chiamate performClick().

Ecco un paio di motivi per cui potresti voler silenziare l'avviso:

  • Il lavoro che stai eseguendo con il tuo evento touch è solo visivo. Non influisce sul funzionamento effettivo della tua app.
  • Hai un cuore freddo e non ti interessa rendere il mondo un posto migliore per i ciechi.
  • Sei troppo pigro per copiare e incollare il codice che ti ho fornito nell'opzione 1 sopra.

Aggiungere la seguente riga all'inizio del metodo per eliminare l'avviso:

@SuppressLint("ClickableViewAccessibility")

Per esempio:

@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
Stavo usando le visualizzazioni personalizzate a causa dell'utilizzo di caratteri diversi. Come ora in Api 26 introduce nuove funzionalità, i caratteri in xml e per le versioni precedenti usano la libreria di supporto 26 che supporta fino a Api 16. Quindi ho rimosso tutte le visualizzazioni personalizzate. E questo stupido avvertimento viene visualizzato e la soluzione è creare di nuovo alcune di quelle viste personalizzate per le quali sto usando setOnTouchListener. hahaha: D Così strano
Shan Xeeshi

19
Mi chiedo se Google si renda conto di quante ore di sviluppo sprecano con questo. Voglio dire, potrebbero forse gestire questo all'interno dell'API? passare il tempo a creare sottoclassi di visualizzazioni o persino a cercare come risolvere il suo avvertimento fa perdere molte ore.
TatiOverflow

cosa succede se hai bisogno MotionEvent eventdell'oggetto nel tuo doSomething()metodo? Ho bisogno di controllare event.getY().
Mateus Gondim

@MateusGondim, devo dire che non sono ancora molto competente nell'implementazione performClick(). Il mio pensiero iniziale è se event.getY()non è parte integrante dell'evento di clic effettivo (ovvero gli effetti dell'interfaccia utente visiva), quindi spostare di nuovo quella logica su onTouchEvent(). Altrimenti potresti creare una variabile membro di classe per memorizzare il Yvalore dell'ultima azione . Ti suggerisco anche di controllare il codice sorgente per alcune delle visualizzazioni standard, quindi guarda come lo implementa Android. Ho bisogno di studiarli di più da solo.
Suragch

1
@sisisisi, l'avviso viene visualizzato quando esegui l'override onTouchEvent()ma non performClick(). Ciò potrebbe includere uno scorrimento o un clic o qualsiasi altro evento di tocco che stai tentando di catturare.
Suragch

17

Soluzione:

  1. Crea una classe che estenda Button o qualsiasi altra visualizzazione che stai utilizzando e sovrascrivi performClick ()

    class TouchableButton extends Button {
    
        @Override
        public boolean performClick() {
            // do what you want
            return true;
        }
    }
    
  2. Ora usa questo TouchableButton in xml e / o codice e l'avviso sparirà!


18
Questo è davvero disgustoso. Non c'è modo di utilizzare le viste esistenti?
Latte

@Milk No. android.widget.Buttonè hardcoded quindi non ti consente di farlo. E sembra essere molto intenzionale dal team di sviluppo Android.
tom_mai78101

11

Hai provato ad aggiungere:

view.performClick()

o aggiungendo l'annotazione suppresslint:

@SuppressLint("ClickableViewAccessibility")

?


2
Sì. Questo comeup Waring con l'edizione Android Studio 3.0
kas

1
Ok, ho un'alternativa per correggere l'avviso. si prega di consultare: stackoverflow.com/questions/47170075/…
lambda

1

I controlli di visualizzazione personalizzati potrebbero richiedere un comportamento degli eventi di tocco non standard. Ad esempio, un controllo personalizzato può utilizzare il metodo listener onTouchEvent (MotionEvent) per rilevare gli eventi ACTION_DOWN e ACTION_UP e attivare un evento clic speciale. Per mantenere la compatibilità con i servizi di accessibilità, il codice che gestisce questo evento clic personalizzato deve eseguire le seguenti operazioni:

Genera un AccessibilityEvent appropriato per l'azione clic interpretata. Abilitare i servizi di accessibilità per eseguire l'azione di clic personalizzata per gli utenti che non sono in grado di utilizzare un touchscreen. Per gestire questi requisiti in modo efficiente, il tuo codice dovrebbe sovrascrivere il metodo performClick (), che deve chiamare la super implementazione di questo metodo e quindi eseguire tutte le azioni richieste dall'evento click. Quando viene rilevata l'azione di clic personalizzata, il codice dovrebbe quindi chiamare il metodo performClick ().

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.