Computer scienceProgramming languagesPythonFast topic group

Fast topic

3 seconds read

Android was developed at a time when most devices had smaller screen sizes than they do now. But when tablets started to become popular, problems began to appear with the display of applications written for these small screens. Then in Android 3.0, Fragments were introduced. Using Fragments is one of several options for making an application that will work on phones in a vertical or horizontal orientation, as well as tablets with larger displays. In this topic, you will learn all about Fragments and discover how to use them effectively in your apps.

What are Fragments?

A Fragment is like an Activity that can be connected to different parts of an application. However, it is important to understand that they are not the same. This means that a Fragment cannot exist unless it's embedded in an Activity.

Fragments are used in Single Activity Architecture to create Navigation and save state. They can also control how information is displayed on a device based on its screen size. This means that information can be placed on a single tablet screen that would need to be split across several screens on a phone. This type of template is called Master/Detail Flow, and you can see it in use by looking at the version of Telegram messenger designed for tablets.

The way that Telegram looks on a tablet is shown below. The chat list is on the left, and the field containing messages is on the right:

On a phone, these are two separate screens. One contains the list of chats, and the other contains the messages associated with the selected chat:

Fragment lifecycle

Since Fragments are closely intertwined with Activities, their lifecycles are also intertwined. The lifecycle methods that either aren't present in Activities or that have the same name but perform a different role are detailed below:

  • onAttach() is called when a Fragment is first attached to its Activity.
  • onCreate() is very similar to the onCreate() Activity method, but it doesn't have access to the UI in Fragments.
  • onCreateView() creates the Fragment View. Its only recommended use is to inflate the layout.
  • onViewCreated() is called immediately after onCreateView(). It is recommended to use it for logic that works with the View that is returned.
  • onDestroyView() is a method that reports that the View created in onCreateView() is no longer available.
  • onDetach() detaches a Fragment from its associated Activity.

The onStart(), onStop(), onResume(), and onPause() lifecycle callbacks are all identical to the ones inside Activity.

Fragment manager

Fragments inherit from the androidx.fragment.app.Fragment class, which comes from the AndroidX library. But there are also several Fragment subclasses: ListFragment, DialogFragment, PreferenceFragment, WebViewFragment, and others. There are two classes in FragmentManager that can be used to find Fragments associated with an Activity. These are findFragmentById(int id) and findFragmentByTag(String tag). The findFragmentById() method finds a Fragment by an identifier and findFragmentByTag() searches by a given tag. If you want to perform any operations on Fragments, be it replacing, deleting, or hiding them, you need to use the special androidx.app.FragmentTransaction class.

The main methods of the FragmentTransaction class are below:

  • add() adds the Fragment to the Activity.
  • remove() is used to remove the Fragment from the Activity.
  • replace() replaces one Fragment with another.
  • hide() is used to hide the Fragment on the screen.
  • show() shows the Fragment on the screen.

Lastly, it's important to remember that you must call the commit() method at the end of every transaction!

How to use Fragments

Let's now look at an example of how Fragments can be used in practice. We will start by creating a .xml file to contain the markup for our Fragment. Once this has been done, we're ready to import and inherit from the Fragment class:

import androidx.fragment.app.Fragment

class YourFragment : Fragment() {

}

Next, we need to inflate some .xml markup within the Fragment. With an Activity, this is done via the setContentView() method, but with Fragments, we need to return our View from onCreateView() instead. Here we receive a LayoutInflater that can turn an XML layout resource into a View hierarchy, a parent container, and a saved state (which we're not currently going to use). We invoke the LayoutInflater.inflate method, passing our layout resource ID, parent container, and false, meaning “no, I don't want you to attach a newly created hierarchy to the container.” Not attaching the hierarchy is important because FragmentManager will do this on its own.

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? =
    inflater.inflate(R.layout.xml_document_name, container, false)

Now, in the .xml layout for MainActivity, we add a FrameLayout that will be a container for Fragments. After this, in the onCreate()method, you need to add the following check:

setContentView(R.layout.activity_main)

if (savedInstanceState == null) {
    supportFragmentManager.beginTransaction()
        .add(R.id.your_container_id, YourFragment())
        .commit()
}

You should also create a default Fragment in this block of code to avoid the possibility of entering a blank screen. A savedInstanceState check is needed, too. This allows us to avoid a situation where our Activity gets recreated, and Fragments are restored, but we forcibly add our Fragment.

Once the default Fragment has been added, any other Fragments must be added using the replace() method and placed in the back stack via addToBackStack(). This will make it possible to go back either by pressing “back” button or by calling popBackStack() on FragmentManager.

supportFragmentManager.beginTransaction()
    .replace(R.id.your_container_id, YourFragment())
    .addToBackStack(null)
    .commit()

You can utilize other methods from the FragmentManager in the same way.

Master/Detail Flow

At the beginning of this topic, you saw screenshots from Telegram demonstrating the different ways that it displays chats on larger and smaller screens. The chat list on the large screen was on the left and was always available, while on the small screen, it was in a separate window. In this case, the screen is, as it were, divided into two parts: "master" and "detail." "Master" is the part of the screen that displays the chat list, and the "detail" part shows details of the messages associated with a specific chat. You can use Master/Detail Flow to create something similar in your applications. To do this, you start by selecting Master/Detail Flow during the creation of the first Activity:

You then need to specify the name of the objects that will be used in Master/Detail:

Several files are produced when the Master/Detail Flow is created. The ones of most interest are as follows:

  • ItemDetailActivity.kt — the class used to display either the layout from activity_item_detail.xml or the ItemDetailFragment.kt (item_detail.xml) Fragment.
  • ItemDetailFragment.kt — the Fragment used to display the contents of the selected item (item_detail.xml).
  • ItemListActivity.kt — the class responsible for displaying and managing the main list (item_list.xml file) and the action when the list item is selected.
  • activity_item_detail.xml — the layout of the ItemDetailFragment.kt class is used to display the selected item from the list.
  • activity_item_list.xml — the layout of the ItemListActivity.kt class is used to display the main list and contains a floating action button.
  • item_list.xml — the layout to use when displaying the list in full screen.
  • item_list.xml (w900dp) — the layout used to display the list on the side.
  • item_detail.xml — the layout of the ItemDetailFragment.kt, which is used to display the selected object's information from the list. A single file for both full-screen display and when the list is on the side.

That's it! Now, when you use the app on devices with different screen sizes, you will be able to see layouts similar to those shown in the Telegram screenshots:

Conclusion

You now know what Fragments are and how to use them. You've learned about the methods specific to the Fragment lifecycle, how to use FragmentManager, and the way to implement Master/Detail Flow. Remember that Fragments are primarily utilized to ensure apps look good on large screens by making the best use of the available space. They can also help you create an application layout to display when a phone is in horizontal mode.

How did you like the theory?
Report a typo