View Binding with Fragments in Android Jetpack - GeeksforGeeks

25 Feb, 2021
In the Previous article View Binding in Android Jetpack, it’s been discussed why acquiring the ViewBinding feature in the Android project provides a lot of benefits. But when it comes to ViewBinding with fragments the scenario changes. Because the lifecycle of the Fragment is different and that of activity is different Here also things go the same as discussed in the above article the naming conventions of the fragment layout are changed to pascal case and properties of the fragment layout to camel case. For Example, fragment1.xml -> Fragment1Binding and edit_text(id) which is under the fragment’s layout changes to eEditText(camel case) So in this article ViewBinding is discussed using Fragments. A sample video is given below to get an idea about what we are going to do in this article. Note that we are going to implement this project using the Kotlin language. 
Step 1: Create a new empty activity project
Using Android Studio create an empty Activity Android Studio project. Refer to Android | How to Create/Start a New Project in Android Studio?.
Step 2: Enable the ViewBinding feature
Enable the ViewBinding feature by invoking the following code snippet inside the app-level build.gradle file, and click on the “Sync Now” buttons which appear on the top-right corner.
buildFeatures {
       viewBinding = true
}
Refer to the following image if unable to locate the app-level build.gradle file invokes the above build feature.
Step 3: Working with the activity_main.xml file
The main layout of the activity contains two buttons, to toggle fragment 1 and fragment 2, and one Framelayout to hold the fragments inside the CardView. And one Submit button to check when pressed whose fragment’s data is submitted.
To implement the same invoke the following code inside the activity_main.xml file.
XML
<?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:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".MainActivity"    tools:ignore="HardcodedText"    tools:viewBindingIgnore="true">      <Button        android:id="@+id/fragment_1B"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginTop="16dp"        android:text="FRAGMENT 1"        app:layout_constraintEnd_toStartOf="@+id/fragment_2B"        app:layout_constraintHorizontal_bias="0.5"        app:layout_constraintStart_toStartOf="parent"        app:layout_constraintTop_toTopOf="parent" />      <Button        android:id="@+id/fragment_2B"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginTop="16dp"        android:text="FRAGMENT 2"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintHorizontal_bias="0.5"        app:layout_constraintStart_toEndOf="@+id/fragment_1B"        app:layout_constraintTop_toTopOf="parent" />      <androidx.cardview.widget.CardView        android:id="@+id/card_view"        android:layout_width="match_parent"        android:layout_height="256dp"        android:layout_marginStart="16dp"        android:layout_marginTop="16dp"        android:layout_marginEnd="16dp"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintStart_toStartOf="parent"        app:layout_constraintTop_toBottomOf="@+id/fragment_1B">          <FrameLayout            android:id="@+id/fragment_holder"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_marginStart="8dp"            android:layout_marginEnd="8dp" />      </androidx.cardview.widget.CardView>      <Button        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginStart="16dp"        android:layout_marginTop="16dp"        android:layout_marginEnd="16dp"        android:text="SUBMIT"        app:layout_constraintEnd_toEndOf="parent"        app:layout_constraintStart_toStartOf="parent"        app:layout_constraintTop_toBottomOf="@+id/card_view" />  </androidx.constraintlayout.widget.ConstraintLayout>
Output UI:
Step 4: Creating two fragments
Create two fragments, which include text view to represent fragment number edit text and a button. To implement the UI of each fragment you may refer to the following codes.
Fragment 1:
XML
<?xml version="1.0" encoding="utf-8"?><!--fragment 1--><LinearLayout     xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context=".ExampleFragment1"    tools:ignore="HardcodedText">      <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginStart="16dp"        android:layout_marginTop="16dp"        android:text="Fragment 1"        android:textSize="18sp" />      <EditText        android:id="@+id/edit_text1"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginStart="16dp"        android:layout_marginTop="16dp"        android:layout_marginEnd="16dp"        android:hint="Enter Something" />      <Button        android:id="@+id/done_button1"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="end"        android:layout_marginTop="8dp"        android:layout_marginEnd="16dp"        android:text="DONE" />  </LinearLayout>
Fragment 2:
XML
<?xml version="1.0" encoding="utf-8"?><!--fragment 2--><LinearLayout     xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context=".ExampleFragment2"    tools:ignore="HardcodedText">      <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginStart="16dp"        android:layout_marginTop="16dp"        android:text="Fragment 2"        android:textSize="18sp" />      <EditText        android:id="@+id/edit_text2"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginStart="16dp"        android:layout_marginTop="16dp"        android:layout_marginEnd="16dp"        android:hint="Enter Something" />      <Button        android:id="@+id/done_button2"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="end"        android:layout_marginTop="8dp"        android:layout_marginEnd="16dp"        android:text="DONE" />  </LinearLayout>
Step 5: Working with the Fragments.kt files
Firstly the binding variable which is nullable is assigned to null initially, and also when the view of the fragment gets destroyed, again it has to be set null (which in this case _binding).
And to avoid the null check of the nullable binding object, by using the backing property of the kotlin we make another copy of the binding variable (which in this case binding).
However, if the fragment wants to access the views from the host activity, can be done using the findViewById() method.
Invoke the following code inside each of the fragment’s .kt files. Comments are added for better understanding.
Fragment 1:
Kotlin
import android.os.Bundleimport android.view.LayoutInflaterimport android.view.Viewimport android.view.ViewGroupimport android.widget.Buttonimport android.widget.Toastimport androidx.fragment.app.Fragment  // Enter your package name hereimport com.adityamshidlyali.gfgarticle.databinding.Fragment1Binding  class ExampleFragment1 : Fragment() {      // assign the _binding variable initially to null and    // also when the view is destroyed again it has to be set to null    private var _binding: Fragment1Binding? = null      // with the backing property of the kotlin we extract    // the non null value of the _binding    private val binding get() = _binding!!      override fun onCreateView(            inflater: LayoutInflater, container: ViewGroup?,            savedInstanceState: Bundle?    ): View {          // inflate the layout and bind to the _binding        _binding = Fragment1Binding.inflate(inflater, container, false)          // retrieve the entered data by the user        binding.doneButton1.setOnClickListener {            val str: String = binding.editText1.text.toString()            if (str.isNotEmpty()) {                Toast.makeText(activity, str, Toast.LENGTH_SHORT).show()            } else {                Toast.makeText(activity, "Please Enter Data", Toast.LENGTH_SHORT).show()            }        }          // handle the button from the host activity using findViewById method        val submitButton: Button = activity!!.findViewById(R.id.submit_button)        submitButton.setOnClickListener {            Toast.makeText(activity, "Host Activity Element Clicked from Fragment 1", Toast.LENGTH_SHORT).show()        }          // Inflate the layout for this fragment        return binding.root    }      override fun onDestroyView() {        super.onDestroyView()        _binding = null    }}
Fragment 2:
Kotlin
import android.os.Bundleimport android.view.LayoutInflaterimport android.view.Viewimport android.view.ViewGroupimport android.widget.Buttonimport android.widget.Toastimport androidx.fragment.app.Fragment  // Enter your package name hereimport com.adityamshidlyali.gfgarticle.databinding.Fragment2Binding  class ExampleFragment2 : Fragment() {      // assign the _binding variable initially to null and    // also when the view is destroyed again it has to be     // set to null    private var _binding: Fragment2Binding? = null      // with the backing property of the kotlin    // we extract    // the non null value of the _binding    private val binding get() = _binding!!      override fun onCreateView(            inflater: LayoutInflater, container: ViewGroup?,            savedInstanceState: Bundle?    ): View {          // inflate the layout and bind to the _binding        _binding = Fragment2Binding.inflate(inflater, container, false)          // retrieve the entered data by the user        binding.doneButton2.setOnClickListener {            val str: String = binding.editText2.text.toString()            if (str.isNotEmpty()) {                Toast.makeText(activity, str, Toast.LENGTH_SHORT).show()            } else {                Toast.makeText(activity, "Please Enter Data", Toast.LENGTH_SHORT).show()            }        }          // handle the button from the host activity using findViewById method        val submitButton: Button = activity!!.findViewById(R.id.submit_button)        submitButton.setOnClickListener {            Toast.makeText(activity, "Host Activity Element Clicked from Fragment 2", Toast.LENGTH_SHORT).show()        }          // Inflate the layout for this fragment        return binding.root    }      override fun onDestroyView() {        super.onDestroyView()        _binding = null    }}
Step 6: Working with the MainActivity.kt file
In the MainActivity.kt file only the transaction functionality of the fragments is implemented. Refer to the following code and its output for better understanding.
Kotlin
import androidx.appcompat.app.AppCompatActivityimport android.os.Bundleimport androidx.fragment.app.Fragmentimport com.adityamshidlyali.gfgarticle.databinding.ActivityMainBinding  class MainActivity : AppCompatActivity() {      // create binding instance for the activity_main.xml    private lateinit var binding: ActivityMainBinding      override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        binding = ActivityMainBinding.inflate(layoutInflater)        setContentView(binding.root)          // when app is initially opened the Fragment 1 should be visible        supportFragmentManager.beginTransaction().apply {            replace(binding.fragmentHolder.id, ExampleFragment1())            addToBackStack(null)            commit()        }          // handle the fragment 2 button to toggle the fragment 2        binding.fragment1B.setOnClickListener {            changeFragment(ExampleFragment1())        }          // handle the fragment 2 button to toggle the fragment 2        binding.fragment2B.setOnClickListener {            changeFragment(ExampleFragment1())        }    }      // function to change the fragment which is used to reduce the lines of code    private fun changeFragment(fragmentToChange: Fragment): Unit {        supportFragmentManager.beginTransaction().apply {            replace(binding.fragmentHolder.id, fragmentToChange)            addToBackStack(null)            commit()        }    }}
Android-Jetpack
Technical Scripter 2020
Android
Kotlin
Technical Scripter
Android
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Resource Raw Folder in Android Studio
Flutter - Custom Bottom Navigation Bar
How to Read Data from SQLite Database in Android?
Retrofit with Kotlin Coroutine in Android
How to Post Data to API using Retrofit in Android?
Kotlin Array
Android UI Layouts
Retrofit with Kotlin Coroutine in Android
How to Get Current Location in Android?
Kotlin Setters and Getters