Wie kann ich das onClick-Ereignis einer Ansicht unter Android an das übergeordnete Ereignis übergeben?

99

Ich habe eine Textansicht in einem Layout, dessen Hintergrund ein Selektor ist. Der Text von TextView ist auf Von HTML überspannt eingestellt. Dann setze ich die Textansicht mit der LinkMovementMethod.

Wenn ich jetzt auf die Textansicht tippe, wird das Klickereignis nicht an das übergeordnete Layout gesendet, um die Auswahl auszulösen.

Wie soll das gelöst werden?

Shiami
quelle

Antworten:

45

Ich denke, Sie müssen eine dieser Methoden verwenden, um das Ereignis abfangen zu können, bevor es an die entsprechenden Komponenten gesendet wird:

Activity.dispatchTouchEvent(MotionEvent) - Auf diese Weise kann Ihre Aktivität alle Berührungsereignisse abfangen, bevor sie an das Fenster gesendet werden.

ViewGroup.onInterceptTouchEvent(MotionEvent) - Auf diese Weise kann eine ViewGroup Ereignisse überwachen, wenn sie an untergeordnete Ansichten gesendet werden.

ViewParent.requestDisallowInterceptTouchEvent(boolean) - Rufen Sie dies bei einer übergeordneten Ansicht auf, um anzugeben, dass Berührungsereignisse nicht mit onInterceptTouchEvent (MotionEvent) abgefangen werden sollen.

Weitere Informationen hier .

Hoffentlich hilft das.

Luis Miguel Serrano
quelle
1
Gibt es eine einfachere Möglichkeit, die Ereignisse zu übergeben, um onClick und onLongClick in der übergeordneten Ansicht auszulösen, oder muss ich sie selbst implementieren?
Shiami
Überprüfen Sie dies: stackoverflow.com/questions/2136696/pass-event-to-parent-view Möglicherweise möchten Sie versuchen, denselben Klick-Listener wie vorgeschlagen an die anderen Instanzen zu übergeben, obwohl ich nicht weiß, ob es funktionieren wird , könnte aber einen Versuch wert sein.
Luis Miguel Serrano
Antwort unten ist viel sauberer
JPM
Soll ich das MotionEvent instanziieren? Bitte erklären Sie, @LuisMiguelSerrano
olegario
@olegario, normalerweise definieren Sie die Methode beispielsweise für dispatchTouchEvent mit @Override neu, um ein neues Verhalten dafür zu definieren, sodass Sie nur ein Bewegungsereignis erhalten, das das System für Ihre Aktivität (oder eine andere Komponente Ihrer Anwendung) bereitgestellt hat, und Sie Behandeln Sie es und / oder leiten Sie es nach Ihren eigenen Regeln an eine beliebige Anzahl von untergeordneten Komponenten weiter. So etwas wie: @Override public boolean dispatchTouchEvent(MotionEvent ev) { ... }
Luis Miguel Serrano
212

Deklarieren Sie Ihre TextViewnicht anklickbar / fokussierbar mit android:clickable="false"und android:focusable="false"oder v.setClickable(false)und v.setFocusable(false). Die Klickereignisse sollten jetzt an das TextViewübergeordnete Element gesendet werden.

Hinweis:

Um dies zu erreichen , müssen Sie einen Klick zu seiner direkten hinzufügen parent. oder set android:clickable="false"und android:focusable="false"an sein direktes übergeordnetes Element , um den Listener an ein weiteres übergeordnetes Element zu übergeben .

siyb
quelle
1
Oh Mann, wenn ich diese +100 geben könnte, würde ich. Ich habe versucht herauszufinden, wie ein Klick nur in einem ViewPager und nicht im Adapterlayout funktioniert, wenn TouchImageView onTouch implementiert! Diese Lösung wirkte wie ein Zauber.
JPM
1
aber was ist, wenn ich das Fokusänderungsereignis von EditText behandeln möchte?
SweetWisher
2
Das Szenario ist: Ich habe ein Layout, das Edittext, relatives Layout, Drehfeld und Listenansicht enthält. Ich möchte ein Berührungsereignis des übergeordneten Layouts auslösen, wenn ich irgendwo auf dem Bildschirm etwas berühre, außer dem Edittext und dem Spinner
SweetWisher
9
Etwas Wichtiges zu bedenken ist , dass , wenn Sie verwenden , TextView#setOnClickListener()auf die TextViewes anklickbare wird, auch wenn es als deklariert ist android:clickable="false", und auch wenn die die ClickListenerfestgelegt ist null( setOnclickListener(null))
Christian García
3
Unterhaltsame Tatsache: Wenn es in TextView ein android:inputTypeAttribut gibt, werden Klickereignisse stillschweigend verbraucht, selbst wenn clickable : false & focusable: false; In meinem Fall war es in einem Stil eingestellt und es kostete mich 30 Minuten, um die Ursache herauszufinden.
Kirill Karmazin
18

Manchmal hilft nur das:

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

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

Eine andere Variante funktioniert nicht immer:

child.setOnClickListener(null);
Alexander Ukhov
quelle
Dieser arbeitete für CardViewals Kind Ansicht, da CardViewscheint zu ignorieren clickable="false"und focusable="false". Wenn Sie jedoch stattdessen das übergeordnete Element verwenden setOnTouchListenerund anrufen, onTouchEventkann das übergeordnete Element Berührungsfeedback anzeigen (z. B. Welligkeitseffekt).
Methodensignatur
Ich habe den relevanten Code unten veröffentlicht: stackoverflow.com/a/52928884/5652513 .
Methodensignatur
10

Stellen

android:duplicateParentState="true"

Beim Kind erhalten die Ansichten dann ihren zeichnbaren Zustand (fokussiert, gedrückt usw.) von ihrem direkten Elternteil und nicht von sich selbst. Sie können onclick für Eltern festlegen und es ruft das Kind an, auf das geklickt wird

Ahmad Ronagh
quelle
OP möchte den Klick-Listener der Eltern aufrufen, wenn auf das Kind geklickt wird, nicht umgekehrt.
Farid
3

Wenn Sie TextViewProbleme beim Erstellen von Klicks haben, entfernen Sie diese android:inputType=""aus Ihrer XML-Datei.

Sanjay Chaudhary
quelle
Wenn Sie nicht wissen warum, empfehle ich Ihnen, es nicht zu tun. Ich sage nur ... zu jedem sein eigenes.
Dell116
Sie sollten es aufandroid:inputType="none"
AZ_
1

Diese Antwort ähnelt der Antwort von Alexander Ukhov , außer dass Touch-Ereignisse anstelle von Klickereignissen verwendet werden. Diese Ereignisse ermöglichen es dem Elternteil, die richtigen Druckzustände anzuzeigen (z. B. Welligkeitseffekt). Diese Antwort ist auch in Kotlin anstelle von Java.

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

Wenn Sie beide OnTouchund OnClickdie Eltern- und Kinderansicht beide anhören möchten , verwenden Sie bitte den folgenden Trick:

  1. Benutzer ScrollView als übergeordnete Ansicht und innerhalb dieser Ansicht Ihre untergeordnete Ansicht in Relative / LinearLayout.

  2. Machen Sie die übergeordnete ScrollView android:fillViewport="true"so, dass die Ansicht nicht gescrollt wird .

  3. Stellen Sie dann den OnTouchListener auf übergeordnet und den OnClickListener auf untergeordnete Ansichten ein. Und genießen Sie beide Hörer-Rückrufe.

Kishor Patil
quelle