Qual è il significato del valore booleano restituito da un metodo di gestione degli eventi in Android


110

In Android, la maggior parte dei metodi del listener di eventi restituisce un valore booleano. Cosa significa questo valore vero / falso? cosa risulterà negli eventi della sottosequenza?

class MyTouchListener implements OnTouchListener {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        logView.showEvent(event);
        return true;
    }
}

Per quanto riguarda l'esempio sopra, se restituisce true nel metodo onTouch , ho scoperto che ogni evento di tocco (DOWN, UP, MOVE, ecc.) È stato catturato in base al mio logView . Al contrario, se restituisce false, viene catturato solo l'evento DOWN. Quindi sembra che return false impedisca la propagazione dell'evento. Ho ragione ?

Inoltre, in un OnGestureListener , molti metodi devono restituire anche un valore booleano. Hanno lo stesso significato?

Risposte:


140

Se torni trueda un ACTION_DOWNevento, sei interessato al resto degli eventi in quel gesto. Un "gesto" in questo caso significa tutti gli eventi fino alla finale ACTION_UPo ACTION_CANCEL. Tornare falseda un ACTION_DOWNmezzo significa non volere l'evento e altre visioni avranno l'opportunità di gestirlo. Se hai viste sovrapposte, questa può essere una vista di pari livello. In caso contrario, ribollirà al genitore.


3
adamp, c'è un modo per continuare a ricevere eventi E far passare gli eventi?
ticofab

@ticofab no, solo un genitore della vista che sta attualmente ricevendo eventi può intercettare eventi futuri nel gesto. (Ovviamente, puoi sempre creare i tuoi sistemi di reindirizzamento in una vista genitore, ma non lo consiglierei a meno che tu non sappia davvero cosa stai facendo. :))
adamp

@adamp Non riesco a pensare al motivo per cui onTouch viene chiamato 2 volte quando restituisco true e 1 volta solo quando restituisco false.
Bhargav Jhaveri

1
@adamp: sto restituendo false da ACTION_DOWN ma il mio ACTION_UP viene attivato ed eseguito.
Mahantesh M Ambi

Sto sbagliando questa risposta o tutti gli altri sono ... Questa risposta ha detto che il ritorno vero significa che l'evento difficile non viene consumato. Ma la verità è completamente inversa.
Kai Wang


12

Il valore booleano determina se l'evento viene consumato o meno.

Sì, hai ragione. Se restituisci false, il listener successivo gestisce l'evento. Se restituisce true, l'evento viene consumato dal tuo ascoltatore e non inviato al metodo successivo.


2
Questo è falso. truesignifica che hai consumato l'evento e desideri il resto degli eventi nel gesto: gli altri ascoltatori / visualizzazioni non riceveranno gli eventi. falsesignifica lasciare che qualcun altro gestisca l'evento. In realtà è un po 'più specifico di quello però; vedere la mia risposta.
adamp

Com'è che non è esattamente quello che ho detto?
Falmarri

1
Quello che hai detto è invertito. :)
adamp

4

Tutta la risposta sopra è corretta ma il risultato è diverso se la vista lo è clickableo menoclickable

Esempio , ho un LinearLayoutcontiene 1 Buttone 1 TextViewcome questo

<LinearLayout
    android:id="@+id/linearlayout_root"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#0aa"
    android:orientation="vertical">

    <Button
        android:id="@+id/button_click"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="40dp"
        android:text="Button Click"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/textview_click"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="40dp"
        android:text="TextView Click"
        android:textSize="20sp"
        android:background="#e4e4e4"
        />

</LinearLayout>

In Activity, ho un codice come

class MainActivity : AppCompatActivity() {
    val TAG = "TAG"

    @SuppressLint("ClickableViewAccessibility")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        findViewById<LinearLayout>(R.id.linearlayout_root).setOnTouchListener { v, event ->
            Log.i(TAG, "LinearLayout onTouch event " + getDisplayAction(event.action))
            false
        }

        findViewById<Button>(R.id.button_click).setOnTouchListener { v, event ->
            Log.i(TAG, "Button onTouch event " + getDisplayAction(event.action))
            false
        }

        findViewById<TextView>(R.id.textview_click).setOnTouchListener { v, event ->
            Log.i(TAG, "TextView onTouch event " + getDisplayAction(event.action))
            false
        }
    }

    private fun getDisplayAction(action: Int): String {
        return when (action) {
            MotionEvent.ACTION_DOWN -> "DOWN"
            MotionEvent.ACTION_MOVE -> "MOVE"
            MotionEvent.ACTION_UP -> "UP"
            MotionEvent.ACTION_CANCEL -> "CANCEL"
            MotionEvent.ACTION_OUTSIDE -> "OUTSIDE"
            else -> "UNKNOWN"
        }
    }
}

Caso 1 Linear onTouch return **FALSE**, Button onTouch return **FALSE**,TextView onTouch return **FALSE**

Fare clic sul pulsante

I/TAG: Button onTouch eventDOWN
I/TAG: Button onTouch eventMOVE
I/TAG: Button onTouch eventUP

Fare clic su TextView

TAG: TextView onTouch eventDOWN
TAG: LinearLayout onTouch eventDOWN

Fare clic su LinearLayout

TAG: LinearLayout onTouch eventDOWN

Caso 2 Linear onTouch return **FALSE**, Button onTouch return **TRUE**,TextView onTouch return **TRUE**

Fare clic sul pulsante

Similar to case 1

Fare clic su TextView

TAG: TextView onTouch event DOWN
TAG: TextView onTouch event MOVE
TAG: TextView onTouch event UP

Fare clic su LinearLayout

Similar to case 1

Caso 3 Linear onTouch return **TRUE**, Button onTouch return **FALSE**,TextView onTouch return **FALSE**

Fare clic sul pulsante

Similar to case 1

Fare clic su TextView

TAG: TextView onTouch event DOWN
TAG: LinearLayout onTouch event DOWN
TAG: LinearLayout onTouch event MOVE
TAG: LinearLayout onTouch event UP

Fare clic su LinearLayout

TAG: LinearLayout onTouch event DOWN
TAG: LinearLayout onTouch event MOVE
TAG: LinearLayout onTouch event UP

Nota

  • L'impostazione predefinita TextViewè not clickable, diventerà cliccabile se impostiamo android:clickable="true"in xml OR quando impostiamotextView.setOnClickListener(...)
  • Quando event MOVEesegui il debug, puoi chiamare più del mio registro (si basa su come tocchi)

Sommario

  • onTouchtornare trueo visualizzare è clickable , Visualizza riceverà tutto onTouchEvent
  • onTouchreturn falsee view no clickable, view non riceverà NEXT onTouchEvent (il genitore potrebbe riceverlo)

Spero che aiuti
DEMO


1
Questa dovrebbe essere la risposta! Grazie per una spiegazione così dettagliata
Mysterious_android

1

Ho perso quasi un giorno nella risoluzione dei problemi, ma ho scoperto che la mia funzione onTouch viene chiamata 2 volte quando si usa true e 1 volte quando si usa false.


Potresti scoprire il motivo?
Bhargav Jhaveri

controlla event.getAction()perché se torni falseall'evento ACTION_DOWN, l'evento ACTION_UP viene ignorato dall'ascoltatore
doodeec

0

Dal documento Android :

Nota: Android chiamerà prima i gestori di eventi e poi i gestori predefiniti appropriati dalla definizione della classe per secondo. Pertanto, la restituzione di true da questi listener di eventi interromperà la propagazione dell'evento ad altri listener di eventi e bloccherà anche il callback al gestore di eventi predefinito nella vista. Quindi assicurati di voler terminare l'evento quando ritorni true.

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.