Cómo usar Ver enlace en vistas personalizadas

6 minutos de lectura

avatar de usuario
Emad Razavi

View Binding se lanzó como parte de Android Jetpack

Documentos: https://developer.android.com/topic/libraries/view-binding

Mi pregunta es cómo usar el enlace de vista con vistas personalizadas. La documentación de Google solo muestra Actividad y fragmento.

Intenté esto, pero no se mostró nada.

LayoutInflater inflater = LayoutInflater.from(getContext());

Y luego, usé este, pero de nuevo, sin suerte.

LayoutInflater inflater = (LayoutInflater)
            getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

Supongo que tal vez no apunte al inflador de diseño correcto para mi vista, pero no estoy seguro.

  • Consulte los adaptadores de unión: desarrollador.android.com/topic/libraries/data-binding/…

    – Guerrero Ruthwik

    27 de febrero de 2020 a las 12:47

  • @RuthwikWarrier ¿Podría dar más detalles? porque estoy preguntando sobre el enlace de vista, no el enlace de datos.

    –Emad Razavi

    27 de febrero de 2020 a las 12:50

  • Hay una pregunta similar con una respuesta válida: stackoverflow.com/a/60425755/7339798

    – Volodymyr Buberenko

    30 de marzo de 2020 a las 19:14

  • @RuthwikWarrier, lamento no estar de acuerdo, pero la pregunta es sobre el enlace de vista desarrollador.android.com/topic/libraries/view-binding en lugar de enlace de datos como enlace proporcionado por usted

    – peter_budo

    13 de diciembre de 2020 a las 16:22

avatar de usuario
Androiderson

Solo informe a la raíz y si desea adjuntarla

init { // inflate binding and add as view
    binding = ResultProfileBinding.inflate(LayoutInflater.from(context), this)
}

o

init { // inflate binding and add as view
    binding = ResultProfileBinding.inflate(LayoutInflater.from(context), this, true)
}

qué método de inflado usar dependerá del tipo de diseño raíz en xml.

  • ¿Qué hay de inflar la vista del recurso de diseño existente? Me gusta init { inflate(context, R.layout.my_view, this) }?

    – anticafé

    8 de junio de 2020 a las 1:56

  • ¿Debo establecer el binding variable a null en algún lugar, similar a cómo deben implementarse en fragmentos?

    – Emilio S.

    11 de febrero de 2021 a las 16:46

  • ¿Necesitamos establecer la referencia en nulo en alguna parte?

    -Gordon Tseng

    16 de febrero de 2021 a las 22:47

  • NO establezca los enlaces en nulo. No hay necesidad. Un Fragmento puede sobrevivir a la destrucción de su vista. Una vista personalizada no puede.

    – Nino DELCEY

    6 abr a las 14:54

  • No es necesario establecer el enlace en nulo en las vistas, solo en Fragmentos. developer.android.com/topic/libraries/view-binding#fragments

    -Den Drobiazko

    11 abr a las 10:49

avatar de usuario
Pavneet_Singh

Para usar el enlace de vista, debe usar la clase de enlace generada, no el LayoutInflaterpor ejemplo, si el nombre del diseño es result_profile.xml entonces necesitas usar ResultProfileBinding como:

class CustomView @kotlin.jvm.JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

    private lateinit var binding: ResultProfileBinding

    init { // inflate binding and add as view
        binding = ResultProfileBinding.inflate(LayoutInflater.from(context))
        addView(binding.root)
    }

}
  1. Clase generada automáticamente: result_profile.xml -> ResultProfileBinding(nombre del diseño, adjunto con Binding )
  2. Inflar la unión

    ResultProfileBinding.inflate(LayoutInflater.from(context))
    
  3. Usar addView para agregar la vista en la jerarquía como:

    addView(binding.root)
    

Nota: Si se extiende desde ConstraintLayout(es la clase principal) luego use el conjunto de restricciones

  • Gracias. Su respuesta puede ser útil en algunas partes, pero necesito una forma de usar el enlace de vista para inflar con la vista raíz sin agregar la vista a la vista raíz.

    –Emad Razavi

    27 de febrero de 2020 a las 13:08

  • @EmiRaz si se crea su vista personalizada (java/kotlin), agregue su vista personalizada en el diseño XML y luego puede acceder directamente a su vista personalizada desde el binding objeto como binding.customview o si desea usar el enlace de vista como suena (how to use view binding with custom views) luego siga la respuesta. para su información: inflater se usa para inflar nuevas vistas usando los diseños xml

    – Pavneet_Singh

    27 de febrero de 2020 a las 13:17


  • Si infla la vista en el bloque de inicio (como pregunta @EmiRaz), simplemente termina en un bucle infinito donde la inflación vuelve a llamar al bloque de inicio. Él está preguntando cómo usar CustomViewBinding dentro de CustomView

    – Jason Toms

    27 de febrero de 2020 a las 13:22

  • @Downvoter: ¿puedo saber el motivo del voto negativo? ya que claramente agregué los detalles sobre cómo usar la vista personalizada con enlace de vista y agregué los detalles faltantes en el OP en los comentarios

    – Pavneet_Singh

    27 de febrero de 2020 a las 13:22

  • @JasonToms, ¿por qué crearía un bucle? ¿Lo has probado? ya que usaremos la clase de enlace generada del diseño en nuestra vista personalizada

    – Pavneet_Singh

    27 de febrero de 2020 a las 13:26

avatar de usuario
levon petrosyan

Puede inicializar la propiedad de enlace de vista de inmediato

private val binding = CustomViewBinding.inflate(LayoutInflater.from(context), this)

  • ¿Puede ser perezoso?

    – Amigo Kanchan

    1 de septiembre de 2021 a las 18:08

  • Puede, pero creo que, a menos que esté haciendo un enlace pesado, no debe hacerlo perezoso, ya que conlleva una sobrecarga adicional.

    – Levon Petrosián

    1 sep 2021 a las 20:07

  • No puede si su CustomView tiene como raíz un ConstraintLayout

    – Skizo-ozᴉʞS

    18 de noviembre de 2021 a las 16:26

avatar de usuario
jason toms

Si está tratando de usar View Binding con la vista raíz, esto funciona para mí:

class CustomView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {

    private lateinit var binding: CustomViewBinding

    override fun onFinishInflate() {
        super.onFinishInflate()
        binding = CustomViewBinding.bind(this)
    }
}

Esta es la respuesta de Kotlin más simple que se me ocurre. Es una vista personalizada que simplemente envuelve un solo TextView y proporciona un update(s:String) Función para actualizar el texto.

<!-- view_stub.xml -->
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView android:id="@+id/myTextView" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" />
</layout>

// StubView.kt
class StubView @JvmOverloads constructor(
        context: Context,
        attrs: AttributeSet? = null,
        defStyleAttr: Int = 0
) : FrameLayout(context,attrs,defStyleAttr) {

    val binding = ViewStubBinding.inflate(context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater)
            .also { addView(it.root) }

    fun update(updatedText: String) {
        binding.myTextView.text = updatedText
    }
}

Las dos cosas que me gustan de esta respuesta son:

  1. binding es un val en lugar de un var. Intento limitar el número de vars tanto como sea posible.
  2. los addView está íntimamente relacionado con la val binding utilizando el also {} función de alcance en lugar de una init {} cláusula, haciendo que la instanciación de la View sentirse mucho más declarativo.

Se podría argumentar que el addView() es realmente un efecto secundario y debe estar en el init {} sección para que sea independiente de la declaración de la binding valor Yo diría lo contrario: declarar un val luego alimentarlo a una sección de código que lo necesita no me parece un efecto secundario.

  • ¿Por qué no simplemente attachToParent=true en inflate()? Debería ser equivalente.

    – Jinete del viento

    17 de diciembre de 2020 a las 13:38


  • ¿Por qué no simplemente attachToParent=true en inflate()? Debería ser equivalente.

    – Jinete del viento

    17 de diciembre de 2020 a las 13:38


¿Ha sido útil esta solución?