Come passare l'evento onClick di una visualizzazione al suo genitore su Android?


100

Ho un TextView in un layout il cui sfondo è un selettore. E il testo di TextView è impostato su Spanning da HTML. Quindi ho impostato TextView con LinkMovementMethod.

Ora quando tocco il TextView, l'evento clic non viene inviato al layout padre per attivare il selettore.

Come dovrebbe essere risolto?

Risposte:


45

Penso che sia necessario utilizzare uno di questi metodi per poter intercettare l'evento prima che venga inviato ai componenti appropriati:

Activity.dispatchTouchEvent(MotionEvent) - Ciò consente alla tua attività di intercettare tutti gli eventi di tocco prima che vengano inviati alla finestra.

ViewGroup.onInterceptTouchEvent(MotionEvent) - Ciò consente a un ViewGroup di guardare gli eventi mentre vengono inviati alle viste figlio.

ViewParent.requestDisallowInterceptTouchEvent(boolean) - Chiamalo su una vista genitore per indicare che non deve intercettare eventi di tocco con onInterceptTouchEvent (MotionEvent).

Maggiori informazioni qui .

Spero che aiuti.


1
Esiste un modo più semplice per passare gli eventi per attivare onClick e onLongClick nella visualizzazione genitore o devo implementarli da solo?
shiami

Dai un'occhiata a: stackoverflow.com/questions/2136696/pass-event-to-parent-view Forse potresti provare a passare lo stesso listener di clic alle altre istanze come suggerito, anche se non so se funzionerà , ma potrebbe valere la pena provare.
Luis Miguel Serrano

La risposta di seguito è molto più pulita
JPM

Devo istanziare MotionEvent? Per favore, spiega, @LuisMiguelSerrano
olegario

@olegario, in genere ridefinisci il metodo ad esempio per dispatchTouchEvent, con @Override, per definire un nuovo comportamento per esso, quindi ricevi solo un evento di movimento che il sistema ha fornito alla tua attività (o un altro componente della tua applicazione) e tu trattalo e / o inoltralo a un numero qualsiasi di componenti bambini secondo le tue regole. Qualcosa come: @Override public boolean dispatchTouchEvent(MotionEvent ev) { ... }
Luis Miguel Serrano

212

Dichiara di TextViewnon essere selezionabile / attivabile utilizzando android:clickable="false"e android:focusable="false"o v.setClickable(false)e v.setFocusable(false). Gli eventi di clic dovrebbero essere inviati al TextViewgenitore di ora.

Nota:

Per ottenere ciò , devi aggiungere un clic al suo diretto parent. o imposta android:clickable="false"e android:focusable="false"al suo genitore diretto per passare l'ascoltatore a un altro genitore .


1
Oh amico, se potessi dare questo +100 lo farei. Sto cercando di capire come fare in modo che un clic funzioni solo in un ViewPager e non nel layout degli adattatori con TouchImageView che implementa onTouch! Questa soluzione ha funzionato a meraviglia.
JPM

1
ma cosa succede se voglio gestire l'evento di modifica del focus di EditText?
SweetWisher ツ

2
Lo scenario è: ho un layout che contiene edittext, layout relativo, spinner e visualizzazione elenco. Voglio attivare l'evento touch del layout genitore ogni volta che tocco un punto qualsiasi dello schermo, tranne il testo e la casella di selezione
SweetWisher ツ

9
Una cosa importante da tenere a mente è che se si utilizza TextView#setOnClickListener()su TextView, diventa cliccabile, anche se è dichiarato come android:clickable="false", e anche se il ClickListenerè impostato su null( setOnclickListener(null))
Christian García

3
Curiosità: se in TextView è presente un android:inputTypeattributo, consumerà silenziosamente gli eventi di clic anche con clickable: false & focusable: false; nel mio caso era impostato in uno stile e mi è costato 30 minuti per capire la causa.
Kirill Karmazin

18

A volte solo questo aiuta:

View child = parent.findViewById(R.id.btnMoreText);
    child.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            View parent = (View) v.getParent();
            parent.performClick();
        }
    });

Un'altra variante, funziona non sempre:

child.setOnClickListener(null);

Questo ha funzionato per CardViewla visualizzazione del bambino, poiché CardViewsembra ignorare clickable="false"e focusable="false". Tuttavia, l'utilizzo setOnTouchListenere la chiamata onTouchEvental genitore consente invece al genitore di visualizzare il feedback tattile (ad es. Effetto a catena).
firma del metodo

Ho pubblicato il codice pertinente di seguito: stackoverflow.com/a/52928884/5652513 .
firma del metodo

10

Mettere

android:duplicateParentState="true"

in child allora le viste ottengono il loro stato disegnabile (focalizzato, premuto, ecc.) dal suo genitore diretto piuttosto che da se stesso. puoi impostare un clic per il genitore e chiamare il bambino cliccato


OP vuole chiamare l'ascoltatore di clic del genitore quando si fa clic sul bambino, non saggio viceversa.
Farid

3

Se TextViewcrei problemi con il clic, rimuovilo android:inputType=""dal tuo file xml.


Se non sai perché, ti consiglio di non farlo. Sto solo dicendo ... a ciascuno il suo.
dell116

Dovresti impostarlo suandroid:inputType="none"
AZ_

1

Questa risposta è simile alla risposta di Alexander Ukhov , tranne per il fatto che utilizza eventi di tocco anziché eventi di clic. Questi eventi consentono al genitore di visualizzare gli stati di pressione corretti (ad esempio, effetto a catena). Questa risposta è anche in Kotlin invece che in Java.

view.setOnTouchListener { view, motionEvent ->
    (view.parent as View).onTouchEvent(motionEvent)
}

0

Se vuoi che entrambi OnTouche l' OnClickascoltatore visualizzino entrambi i genitori e il figlio, usa il trucco seguente:

  1. User ScrollView come vista padre e all'interno di quella vista figlio all'interno di Relative / LinearLayout.

  2. Imposta Parent ScrollView in android:fillViewport="true"modo da non far scorrere la vista.

  3. Quindi imposta OnTouchlistener su genitore e OnClicklistener su viste figlio. E goditi entrambi i richiami degli ascoltatori.

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.