© Ted Hagos 2020
T. HagosLearn Android Studio 4https://doi.org/10.1007/978-1-4842-5937-5_9

9. Fragments

Ted Hagos1 
(1)
Manila, National Capital Region, Philippines
 
What we’ll cover:
  • Introduction to Fragments

  • The Fragment class and Fragment resource file

  • Adding Fragments to Activities dynamically

In the early days of Android, when it ran only on phones, and there weren’t any high-resolution screens, activities were sufficient to compose the UI and interact with the user. Then came the tablets and high-resolution displays. It became increasingly difficult to create applications that can run well on both phones and tablets. Developers were faced with hard choices. Either you choose the least capable hardware as the target and make it like the least common denominator or make the app adapt to a range of form factors by removing and adding UI elements in response to the device’s capability, which proved to be very difficult to do manually. When API 11 (Honeycomb) came out, Android solved this problem with Fragments; this is the topic of this chapter.

Introduction to Fragments

If we think of an activity as a composition unit for our UI, think of a fragment as a mini-activity—it’s a smaller composition unit. You will usually show (and hide) fragments during runtime in response to something that a user did, for example, tilting the device, switching from portrait to landscape orientation, thus making more screen space available. You may even use fragments as a strategy to adapt to device form factors. When the app is running on a smaller screen, you will show only some of the fragments.

Like an activity, a fragment comprises two parts—a Java program and a layout file. The idea is almost the same—define the UI elements in an XML file and then inflate the XML file in a program file so that all the view objects in the XML will become an object. After that, we can reference each view object in the XML using the R.class. Think of a fragment as an ordinary view object that we can drag and drop on the main layout file.

To create a Fragment, we generally do the following:
  1. 1.

    Create an XML resource file and put it in the /app/res/layout folder, just like where we put activity_main.xml.

     
  2. 2.

    Give the new resource file a descriptive name, say fragment_booktitles.

     
  3. 3.

    Create the Fragment class; this class must inherit androidx.fragment.app.Fragment—all support libraries are now in the androidx package.

     
  4. 4.

    Next, hook up the Fragment class with the XML resource layout. You can inflate the XML resource file in the onCreate() method of the Fragment class.

     
  5. 5.

    Make some changes to MainActivity. The default MainActivity inherits from AppCompatActivity; this is usually fine, but we are using the Fragment class from the support library, which means we need to inherit from FragmentActivity instead of the default AppCompatActivity.

     
  6. 6.

    Add the newly created Fragment.

     

Let’s do them in Android Studio. First, create a project with an empty Activity, just like all the other projects we’ve created.

Let’s create an XML resource file and put it in /app/res/layout. You can do that by right-clicking the project’s layout folder, then choosing NewLayout Resource File, as shown in Figure 9-1.
../images/457413_2_En_9_Chapter/457413_2_En_9_Fig1_HTML.jpg
Figure 9-1

New Layout Resource File

In the window that follows, type the filename of the new resource file (fragment_booktitles), as shown in Figure 9-2.
../images/457413_2_En_9_Chapter/457413_2_En_9_Fig2_HTML.jpg
Figure 9-2

New Resource File

Next, let’s add a fragment class. To do that, add a Java class to the project by right-clicking the project’s package, then choosing NewJava Class, as shown in Figure 9-3.
../images/457413_2_En_9_Chapter/457413_2_En_9_Fig3_HTML.jpg
Figure 9-3

Add a Java class

In the pop-up window that follows, type the name of the new Java class (BookTitle), as shown in Figure 9-4.
../images/457413_2_En_9_Chapter/457413_2_En_9_Fig4_HTML.jpg
Figure 9-4

New Java Class

Edit the fragment_booktitles layout file to match Listing 9-1. You can add whatever View component you want to add; for my purpose, I simply added a TextView object.
<?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">
  <TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="122dp"
    android:text="MyFragment"
    android:textSize="36sp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Listing 9-1

app/res/layout/fragment_booktitles.xml

Next, modify the BookTitle class to match Listing 9-2.
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import static com.example.ch9fragments.R.layout.*;
public class BookTitle extends Fragment {
  @Nullable
  @Override
  public View onCreateView(@NonNull LayoutInflater inflater,
                           @Nullable ViewGroup container,
                           @Nullable Bundle savedInstanceState) {
    final View view = inflater.inflate(fragment_booktitles, container, false);
    return view;
  }
}
Listing 9-2

BookTitle class

We can associate the fragment layout file (fragment_booktitles) with the fragment class (BookTitle) by inflating the layout file and returning it from within the onCreateView() callback.

The onCreateView() callback is similar to the onCreate() method of the Activity class, but be careful not to refer to any View element here because they won’t be available just yet. If you need to refer to any View element contained in the fragment layout file, you have to do that in the onViewCreated() callback (not shown here). The reason you can’t refer to any View element inside the onCreateView() callback is because you have yet to inflate the layout resource file, so, naturally, they won’t be there just yet.

Next, let’s edit MainActivity. We need to change the parent class of MainActivity from AppCompactActivity to FragmentActivity—because we’re using Fragments. Listing 9-3 shows the code for MainActivity.
import androidx.fragment.app.FragmentActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends FragmentActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
  }
}
Listing 9-3

MainActivity

If you want to display the fragment we created, you can edit the activity_main layout file, then drag and drop the <fragment> element from the palette (as shown in Figure 9-5). When you run the app, the fragment will appear in the Activity like any other View element.
../images/457413_2_En_9_Chapter/457413_2_En_9_Fig5_HTML.jpg
Figure 9-5

<fragment>

Alternatively, you can display the fragment programmatically. To do that, we need a placeholder for the fragment and perhaps a Button element (to serve as an action trigger for when we’re about to display the fragment). Edit activity_main.xml to match Listing 9-4.
<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">
  <Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="1dp"
    android:text="Button"
    app:layout_constraintStart_toStartOf="@+id/fragplaceholder"
    app:layout_constraintTop_toTopOf="@+id/fragplaceholder" />
  <FrameLayout
    android:id="@+id/fragplaceholder"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:layout_marginBottom="1dp"
    android:layout_marginEnd="1dp"
    android:layout_marginStart="1dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="1.0"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.0">
  </FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Listing 9-4

app/res/layout/activity_main

I’ve added a Button and a FrameLayout container to activity_main. I gave the FrameLayout an id of fragplaceholder (you can give it any name you like) so I can refer to it later.

Adding a Fragment to the MainActivity (dynamically) requires the use of a FragmentTransaction object. To get a FragmentTransaction object, we also need a FragmentManager object. It’s usually done like this:
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Now, we can make fragment transactions. To add the BookTitle fragment to MainActivity, we need two things:
  1. 1.

    An instance of BookTitle

     
  2. 2.

    A ViewGroup which to place the fragment; this is our FrameLayout object

     
In code, it looks like this:
BookTitle booktitle = new BookTitle();
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.fragplaceholder, booktitle);
ft.commit();
To put this all in context, edit MainActivity to match Listing 9-5, which contains the complete code for our small demo app for fragments.
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends FragmentActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button btn = findViewById(R.id.button);
    btn.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        BookTitle booktitle = new BookTitle();
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.add(R.id.fragplaceholder, booktitle);
        ft.commit();
      }
    });
  }
}
Listing 9-5

MainActivity, complete listing

When the app runs, it won’t show the fragment just yet. When you click the Button, the BookTitle fragment will be displayed.

Figure 9-6 shows the fragment app running in an emulator.
../images/457413_2_En_9_Chapter/457413_2_En_9_Fig6_HTML.jpg
Figure 9-6

Fragment app

Summary

  • To create a fragment, you need a layout resource file and a Java class (inheriting from androidx.fragment.app.FragmentActivity).

  • To associate a Fragment class with a fragment layout file, inflate the layout file inside the class’ onCreateView() callback method.

  • To add Fragments programmatically, you need to use FragmentManager and FragmentTransaction objects.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.41.214