tres tipos tag son partes manager las insertar google eventos enlaces cuáles activadores activador android kotlin android-constraintlayout

android - tipos - tag manager url path



Use el grupo en ConstraintLayout para escuchar eventos de clic en vistas múltiples (5)

Básicamente, me gustaría adjuntar un solo OnClickListener a múltiples vistas dentro de un ConstraintLayout.

Antes de migrar a ConstraintLayout, las vistas estaban dentro de un diseño en el que podía agregar un oyente. Ahora están en la misma capa con otras vistas justo debajo de ConstraintLayout.

Intenté agregar las vistas a un android.support.constraint.Group y agregué un OnClickListener a él programáticamente.

group.setOnClickListener { Log.d("OnClick", "groupClickListener triggered") }

Sin embargo, esto no parece funcionar a partir de la versión 1.1.0-beta2 ConstraintLayout.

¿He hecho algo mal, hay alguna forma de lograr este comportamiento o debo adjuntar al oyente a cada una de las vistas individuales?


El Group en ConstraintLayout es solo una asociación de puntos de vista AFAIK. No es un ViewGroup , por lo que no podrá utilizar un detector de un solo clic como lo hizo cuando las vistas estaban en un ViewGroup .

Como alternativa, puede obtener una lista de identificadores que son miembros de su Group en su código y establecer explícitamente la escucha de clics. (No he encontrado documentación oficial sobre esta función, pero creo que solo se está retrasando el lanzamiento del código). Consulte la documentación sobre getReferencedIds here .

Java:

Group group = findViewById(R.id.group); int refIds[] = group.getReferencedIds(); for (int id : refIds) { findViewById(id).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // your code here. } }); }

En Kotlin puedes construir una función de extensión para eso.

Kotlin:

fun Group.setAllOnClickListener(listener: View.OnClickListener?) { referencedIds.forEach { id -> rootView.findViewById<View>(id).setOnClickListener(listener) } }

Luego llama a la función en el grupo:

group.setAllOnClickListener(View.OnClickListener { // code to perform on click event })


El método de extensión es excelente, pero puedes mejorarlo cambiando a

fun Group.setAllOnClickListener(listener: (View) -> Unit) { referencedIds.forEach { id -> rootView.findViewById<View>(id).setOnClickListener(listener) } }

Así que la vocación sería así.

group.setAllOnClickListener { // code to perform on click event }

Ahora la necesidad de definir explícitamente View.OnClickListener ahora se ha ido.

También puede definir su propia interfaz para GroupOnClickLitener de esta manera

interface GroupOnClickListener { fun onClick(group: Group) }

y luego definir un método de extensión como este

fun Group.setAllOnClickListener(listener: GroupOnClickListener) { referencedIds.forEach { id -> rootView.findViewById<View>(id).setOnClickListener { listener.onClick(this)} } }

y usalo asi

groupOne.setAllOnClickListener(this) groupTwo.setAllOnClickListener(this) groupThree.setAllOnClickListener(this) override fun onClick(group: Group) { when(group.id){ R.id.group1 -> //code for group1 R.id.group2 -> //code for group2 R.id.group3 -> //code for group3 else -> throw IllegalArgumentException("wrong group id") } }

El segundo enfoque tiene un mejor rendimiento si el número de vistas es grande, ¡ya que solo usas un objeto como oyente para todas las vistas!


La mejor manera de escuchar los eventos de clic desde múltiples vistas es agregar una vista transparente como un contenedor encima de todas las vistas requeridas. Esta vista debe estar al final (es decir, en la parte superior) de todas las vistas en las que necesita hacer un clic.

Vista del contenedor de muestra

<View android:id="@+id/view_container" android:layout_width="0dp" android:layout_height="0dp" app:layout_constraintBottom_toBottomOf="@+id/view_bottom" app:layout_constraintEnd_toEndOf="@+id/end_view_guideline" app:layout_constraintStart_toStartOf="@+id/start_view_guideline" app:layout_constraintTop_toTopOf="parent"/>

La muestra anterior contiene los cuatro límites de restricción dentro de eso, podemos agregar vistas para escuchar juntos y, como es una vista, podemos hacer lo que queramos, como el efecto de onda.


Para complementar la respuesta aceptada para los usuarios de Kotlin, cree una función de extensión y acepte un lambda para sentirse más como la API group.addOnClickListener { } .

Crear la función de extensión:

fun Group.addOnClickListener(listener: (view: View) -> Unit) { referencedIds.forEach { id -> rootView.findViewById<View>(id).setOnClickListener(listener) } }

uso:

group.addOnClickListener { v -> Log.d("GroupExt", v) }


Si bien me gusta el enfoque general en la respuesta de Vitthalk, creo que tiene un gran inconveniente y dos menores.

  1. No tiene en cuenta los cambios dinámicos de posición de las vistas individuales.

  2. Puede registrar clics para vistas que no forman parte del grupo.

  3. No es una solución genérica para este problema bastante común.

Si bien no estoy seguro de una solución para el segundo punto, claramente hay bastante fáciles para el primero y el tercero.

1. Cambios en la posición contable del elemento en el grupo.

Esto es en realidad bastante simple. Se puede usar el conjunto de herramientas del diseño de restricción para ajustar los bordes de la vista transparente. Simplemente usamos Barriers para recibir las posiciones de la izquierda, de la derecha, etc. de cualquier Vista en el grupo. Luego podemos ajustar la vista transparente a las barreras en lugar de vistas concretas.

3. Solución genérica

Usando Kotlin podemos extender la Clase de grupo para incluir un método que agregue un ClickListener a una Vista como se describió anteriormente. Este método simplemente agrega las barreras al diseño, prestando atención a todos los niños del grupo, la vista transparente que se alinea con las barreras y registra el ClickListener en el último.

De esta manera, simplemente necesitamos llamar al método en el Grupo y no necesitamos agregar las vistas al diseño manualmente cada vez que necesitamos este comportamiento.