ViewBinding o vinculación de vista permite acceder fácilmente al contenido de una vista (XML) a través de los ID de los componentes. Antes la manera de hacer esto era a través del mítico findViewById o utilizando kotlin-android-extensions, pero el problema de los dos anteriores es que podías estar vinculando un componente de otra vista que no era la actual y que se produjera un NullPointerException. Con esta nueva forma de acceder a las vistas evitamos ese problema.
Lo primero de todo es habilitar esta característica en el proyecto, por lo que en el build.gradle escribiremos lo siguiente:
1 2 3 4 5 6 |
android { ... viewBinding { enabled = true } } |
O si tenéis alguna versión antigua del gradle se puede activar de la siguiente manera:
1 2 3 4 5 6 |
android { ... buildFeatures{ viewBinding = true } } |
Una vez activada la funcionalidad, se creará un archivo de vinculación por cada diseño XML que creemos, pudiendo acceder a los elementos utilizando su ID.
Supongamos que tenemos el siguiente diseño y el XML se llama modal_fragment.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/dismissIcon" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingStart="16dp" android:paddingEnd="16dp" android:paddingBottom="16dp" tools:context=".ui.forgot.ForgotFragment"> <androidx.appcompat.widget.AppCompatTextView android:id="@+id/modal_title" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="24dp" android:layout_marginEnd="8dp" android:text="@string/modal_forgot_title" app:layout_constraintEnd_toStartOf="@+id/imageView" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"/> <androidx.appcompat.widget.AppCompatTextView android:id="@+id/modal_subtitle" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:paddingBottom="24dp" android:text="@string/modal_forgot_text" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/modal_title"/> <com.google.android.material.button.MaterialButton android:id="@+id/modal_button" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="2dp" android:text="@string/modal_forgot_button" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/modal_subtitle"/> <ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="18dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" app:srcCompat="@drawable/ic_close"/> </androidx.constraintlayout.widget.ConstraintLayout> |
Al crear el XML ahora automaticamente se ha creado una clase con el mismo nombre de la vista pero con la terminacion binding → ModalFragmentBinding. Lo declaramos como una variable lateinit e instanciamos la vista utilizando esta clase y devolvemos la vista creada (root)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class ModalFragment : Fragment() { private lateinit var binding: ModalFragmentBinding override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { binding = ModalFragmentBinding.inflate(inflater, container, false) return binding.root } } |
Si estamos en una actividad sería exactamente igual:
1 2 3 4 5 6 7 8 9 10 |
class ModalActivity : AppCompatActivity() { private lateinit var binding: ModalActivityBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ModalActivityBinding.inflate(layoutInflater) setContentView(binding.root) } } |
Una vez que tengamos hecho lo anterior, ya podremos acceder a todos los elementos de la vista que tengan un ID a través de la variable binding que hemos inicializado: