Step-by-Step Android Fragments Guide for Dynamic UI Design

Step-by-Step Android Fragments Guide for Dynamic UI Design

Learn how to leverage fragments for creating flexible, multi-panel UIs while managing lifecycles, transactions, and backstack like a pro.

Introduction

A fragment is a small reusable piece of activity that is hosted by an activity. However, they are different from normal activities & have their own lifecycle, and manage their own layout.

We can combine multiple fragments in a single activity to build a multi-panel UI. We can reuse a fragment in multiple activities.

Two versions of the same screen on different screen sizes.

A fragment must run inside an activity as the lifecycle of a fragment depends on its parent activity's lifecycle.

Fragment Creation in Android

Creating a Fragment creates the corresponding Kotlin & XML file associated with the Fragment :

//FirstFragment.kt
import .. 
class FirstFragment : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
       // Inflate the layout for this fragment
       return inflater.inflate(R.layout.fragment_first, container, false)
    }
}
//similarly fragment_first.xml is created

Navigating to Fragment in our Activity :

  • FragmentManager class is responsible for performing actions on fragments such as adding, removing, replacing, and adding them to the back stack. FragmentManager can be accessed both from an activity or from a fragment.

  • Each set of fragment changes that you commit is called a transaction, and we can specify what to do inside the transaction using the APIs provided by the FragmentTransaction class. An instance of FragmentTransaction can be accessed from the FragmentManager by calling the beginTransaction() method. A FragmentTransaction can add, replace or remove fragments & also enable animations during fragment transition.
    We can group multiple actions into a single transaction - for example, a transaction can add or replace multiple fragments.

  • Within the transaction, we can then perform an add() or replace() operation on the layout container.

<!-- activity_main.xml -->
<LinearLayout .. >
    <FrameLayout
        android:id="@+id/frame" .. />
</LinearLayout>
import .. 
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
     super.onCreate(savedInstanceState)
     setContentView(R.layout.activity_main)

     val fragmentManager : FragmentManager = supportFragmentManager
//creating fragment manager - supportFragmentManager is a method of AppCompatActivity class
// used to obtain the FragmentManager
     val fragmentTransaction : FragmentTransaction = fragmentManager.beginTransaction()
//creating fragment transaction
     val firstFragment = FirstFragment()
//creating a object to hold our fragment
     fragmentTransaction.add(R.id.frame,firstFragment)
//create a transaction that adds fragment to the container layout
     fragmentTransaction.commit()
//commit changes
    }
}

Changing Fragment in Activity

In Android, each transaction involving fragments should be done within a transaction block FragmentTransaction. Once a transaction is committed, it cannot be reused. Therefore, when you want to perform another fragment transaction, you need to create a new FragmentTransaction instance.

Creating a new fragment named SecondFragment.

changeBtn.setOnClickListener {
  val fragmentTransaction : FragmentTransaction = fragmentManager.beginTransaction()
  val secondFragment = SecondFragment()
  fragmentTransaction.replace(R.id.frame,secondFragment)
//as we need to replace the previous fragment
  fragmentTransaction.commit()
//commit() call signals to the FragmentManager 
//that all operations have been added to the transaction.
}

Fragment BackStack in Kotlin

By default, the changes made in a FragmentTransaction are not added to the back stack. To save those changes, we need to call the addToBackStack() method on the FragmentTransaction .
Hence, pressing the back button on a fragment UI on which we landed after switching multiple fragments will lead to the closing of the application or the return to the previous activity from the activity back stack.

fragmentTransaction.addToBackStack(null)
//placed before the commit call to the transaction
//hence the change caused by the transaction will be added to the 
//back stack and be reversed during pop.

Fragment Lifecycle

Each Fragment instance has its own lifecycle. When a user navigates and interacts with our app, the fragments transition through various states in their lifecycle as it is added, removed, and entered or exits the screen.

CallBackFunction
onAttach(context : Context)called when the fragment(child) has been associated with the activity(parent) i.e. when the fragment is added to the fragment manager & attached to the host activity. Fragment is not fully created here.
onCreate(savedInstanceState: Bundle?)invoked to initialise the fragment by adding all the required attributes and components, called when the fragment is attached but before the UI is created.
onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?)invoked to create the user interface of the fragment. The root of the fragment’s layout is returned as the View component by this method to draw the UI.
You should inflate your layout in onCreateView but shouldn’t access other views using findViewById, as the fragment UI is getting created.
onViewCreated(view: View?, savedInstanceState: Bundle?)indicates that the activity has been created in which the fragment exists. Can initialise views, set adapters, attach listeners.
onStart()invoked to make the fragment visible on the user’s device.
onResume()invoked to make the visible fragment interactive.
onPause()invoked to indicate that the user is leaving the fragment. The system calls this method to commit the changes made to the fragment.
onStop()Method to terminate the functioning and visibility of the fragment from the user’s screen.

If the Fragment needs to be called again on the screen, the onStart() method is invoked, if not, then the onDestroyView() is invoked to clean up all kinds of resources, onDestroy() is invoked to clean up the fragment’s state and its lifecycle, and onDetach() is invoked to disassociate the fragment from its host activity.