Как передать событие onClick представления его родительскому элементу на Android?

100

У меня есть TextView в макете, чей фон является селектором. И текст TextView установлен на Spanned from HTML. Затем я установил TextView с помощью LinkMovementMethod.

Теперь, когда я нажимаю на TextView, событие щелчка не отправляется в его родительский макет для запуска селектора.

Как это решить?

шиами
источник

Ответы:

45

Я думаю, вам нужно использовать один из этих методов, чтобы иметь возможность перехватить событие, прежде чем оно будет отправлено в соответствующие компоненты:

Activity.dispatchTouchEvent(MotionEvent) - Это позволяет вашей Activity перехватывать все события касания до того, как они будут отправлены в окно.

ViewGroup.onInterceptTouchEvent(MotionEvent) - Это позволяет ViewGroup отслеживать события по мере их отправки дочерним представлениям.

ViewParent.requestDisallowInterceptTouchEvent(boolean) - Вызовите это для родительского View, чтобы указать, что он не должен перехватывать события касания с onInterceptTouchEvent (MotionEvent).

Больше информации здесь .

Надеюсь, это поможет.

Луис Мигель Серрано
источник
1
Есть ли более простой способ передать события для запуска onClick и onLongClick в родительском представлении, или мне нужно реализовать их самостоятельно?
Шиами
Проверьте это: stackoverflow.com/questions/2136696/pass-event-to-parent-view Возможно, вы захотите попробовать передать тот же прослушиватель кликов в другие экземпляры, как предлагается, хотя я не знаю, сработает ли он , но, возможно, стоит попробовать.
Луис Мигель Серрано,
Ответ ниже намного чище
JPM
Должен ли я создать экземпляр MotionEvent? Пожалуйста, объясните, @LuisMiguelSerrano
olegario
@olegario, обычно вы переопределяете метод, например, для dispatchTouchEvent, с помощью @Override, чтобы определить новое поведение для него, поэтому вы просто получаете событие движения, которое система предоставила вашему действию (или другому компоненту вашего приложения), и вы обрабатывать его и / или пересылать любому количеству дочерних компонентов в соответствии с вашими собственными правилами. Что-то вроде: @Override public boolean dispatchTouchEvent(MotionEvent ev) { ... }
Луис Мигель Серрано
214

Объявите, что вы TextViewне кликабельны / фокусируемы, используя android:clickable="false"и android:focusable="false"или v.setClickable(false)и v.setFocusable(false). События щелчка должны быть отправлены наTextView родительскому объекту.

Примечание:

Для этого вам нужно добавить щелчок в его директ parent. или установите android:clickable="false"и android:focusable="false"своему прямому родителю, чтобы передать слушателя следующему родителю .

сийб
источник
1
О, чувак, если бы я мог дать это +100, я бы сделал это. Пытался выяснить, как сделать так, чтобы щелчок работал только в ViewPager, а не в макете адаптеров с TouchImageView, реализующим onTouch! Это решение сработало как шарм.
JPM
1
но что, если я хочу обработать событие изменения фокуса EditText?
SweetWisher ツ
2
Сценарий такой: у меня есть макет, который содержит текст редактирования, относительный макет, счетчик и представление списка. Я хочу запускать событие касания родительского макета всякий раз, когда я касаюсь любого места на экране, кроме текста редактирования и счетчика
SweetWisher ツ
9
Важно помнить, что если вы используете TextView#setOnClickListener()на TextView, он становится интерактивным, даже если он объявлен как android:clickable="false", и даже если для параметра ClickListenerустановлено значение null( setOnclickListener(null))
Кристиан Гарсия,
3
Интересный факт: если в TextView есть android:inputTypeатрибут, он будет молча потреблять события щелчка даже с clickable: false и focusable: false; в моем случае это было оформлено в стиле, и мне потребовалось 30 минут, чтобы выяснить причину.
Кирилл Кармазин
18

Иногда помогает только это:

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

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

Другой вариант, работает не всегда:

child.setOnClickListener(null);
Александр Ухов
источник
Это работало CardViewкак дочернее представление, поскольку, CardViewпохоже, игнорирует clickable="false"и focusable="false". Однако использование setOnTouchListenerи вызов onTouchEventродителя вместо этого позволяет ему отображать сенсорную обратную связь (например, эффект пульсации).
methodignature
Я разместил соответствующий код ниже: stackoverflow.com/a/52928884/5652513 .
methodignature
10

Ставить

android:duplicateParentState="true"

в дочернем элементе представления получают свое доступное для рисования состояние (сфокусировано, нажато и т. д.) от своего прямого родителя, а не от себя. вы можете установить onclick для родителя, и он вызовет нажатие дочернего элемента

Ахмад Рона
источник
OP хочет вызвать родительский прослушиватель кликов при нажатии дочернего элемента, а не наоборот.
Фарид
3

Если вы TextViewсоздаете проблемы с щелчком, удалите их android:inputType=""из XML-файла.

Санджай Чаудхари
источник
Если вы не знаете, почему, я рекомендую вам не делать этого. Просто говорю ... каждому свое.
dell116
Вы должны установить его наandroid:inputType="none"
AZ_
1

Этот ответ похож на ответ Александра Ухова , за исключением того, что он использует события касания, а не события щелчка. Эти события позволяют родителю отображать правильные состояния нажатия (например, эффект пульсации). Этот ответ также находится на Kotlin вместо Java.

view.setOnTouchListener { view, motionEvent ->
    (view.parent as View).onTouchEvent(motionEvent)
}
метод подпись
источник
0

Если вы хотите, чтобы оба OnTouchи OnClickслушатель смотрели и на родителей, и на детей, используйте следующий трюк:

  1. Пользовательский ScrollView в качестве родительского представления и внутри него помещает дочернее представление в Relative / LinearLayout.

  2. Сделайте родительский ScrollView android:fillViewport="true"так, чтобы просмотр не прокручивался.

  3. Затем установите OnTouchслушателя на родительский и OnClickслушатель на дочерние представления. И наслаждайтесь обратными вызовами обоих слушателей.

Кишор Патил
источник