Creating and using fragments

Sometimes normal layouts aren't dynamic enough or we may have to reuse sections of the UI and its related code.

Getting ready

To add fragments to our app we need to be targeting Android version 3.0 and above; for versions below that, we need to have installed the Xamarin.Android.Support.v4 package.

How to do it...

In order to make use of fragments in our apps, we need to create a new fragment type. Then, either in the layout or in the code, we can insert the fragments into their appropriate places in the UI. Let's take a look at the following steps:

  1. To make a master-detail app, we need a menu or list of items to select. For the menu fragment we are going to inherit from ListFragment, which is very similar to ListActivity, and set the ListAdapter property:
    public class MenuFragment : ListFragment {
      public override void OnStart() {
        base.OnStart();
    
        ListAdapter = new ArrayAdapter(
          Activity,
          Android.Resource.Layout.SimpleListItem1,
          new [] {"First", "Second", "Third", "Fourth"});
      }
    }
  2. The other part of a master-detail app is the details. This fragment is going to be a normal fragment, and we will use a separate layout resource to define the UI structure:
    1. The UI for this fragment can be any view hierarchy. Here it is defined in a layout resource file named ContentFragment.axml:
      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
          android:id="@+id/textView"
          android:text="Select an item to the left..."
          android:gravity="center"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          style="@android:style/TextAppearance.Large" />
      </LinearLayout>
    2. The code for the content fragment inflates the resource in the OnCreateView() method:
      public class ContentFragment : Fragment {
        public override View OnCreateView(
          LayoutInflater inflater,
          ViewGroup container,
          Bundle savedInstanceState) {
            return inflater.Inflate(
            Resource.Layout.ContentFragment, container, false);
          }
      }
    3. If we are going to update the UI from outside the fragment, we need to make sure that the fragment provides a means to do so:
      public void Update(string text) {
        var textView = Activity.FindViewById<TextView> (Resource.Id.textView);
        textView.Text = string.Format(
          "You have selected '{0}'...", text);
      }
  3. Now that our fragments are complete, we can start creating the app that will be using these fragments:
    1. We are going to create a layout for the main activity in a file named Main.axml. The layout will display both fragments side by side, by setting the orientation attribute to horizontal:
      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <fragment
          android:name="xamarincookbook.MenuFragment"
          android:id="@+id/menu"
          android:layout_weight="2"
          android:layout_width="match_parent"
          android:layout_height="match_parent" />
        <fragment
          android:name="xamarincookbook.ContentFragment"
          android:id="@+id/content"
          android:layout_weight="1"
          android:layout_width="match_parent"
          android:layout_height="match_parent" />
      </LinearLayout>
    2. We now have to set up the activity to load the layout using the SetContentView() method:
      protected override void OnCreate(Bundle bundle) {
        base.OnCreate(bundle);
        SetContentView(Resource.Layout.Main);
      }
  4. Once we have the basic structure set up for both the fragments and the activity, we add the ability for the menu fragment to communicate with the parent activity, and in turn, the content fragment. Let's take a look at the following steps:
    1. The menu fragment only does one thing—it lets the activity know that the user has selected an item—so we create an interface that represents a contract between the fragment and the activity:
      public interface IMenuSelected {
        void OnMenuSelected(string text);
      }
    2. Next, we ensure that the activity implements the IMenuSelected interface and its OnMenuSelected() method. This method then retrieves the content fragment and updates it. Let's take a look at the following code snippet:
      public void OnMenuSelected(string text) {
        var contentFragment = SupportFragmentManager.FindFragmentById(
            Resource.Id.content) as ContentFragment;
        contentFragment.Update(text);
      }
    3. In the menu fragment, we need to get hold of the activity that we will be communicating with. This can be done by overriding the OnAttach() method of the menu fragment and keeping a reference to the parent activity:
      private IMenuSelected menuSelected;
      
      public override void OnAttach(Activity activity) {
        base.OnAttach(activity);
        menuSelected = activity as IMenuSelected;
      }
    4. Then, to let the activity know when the user selects a menu item, we subscribe to the list's select event and invoke the OnMenuSelected() method of the activity:
      public override void OnStart() {
        // ...
        ListView.ItemClick += (sender, e) => {
          if (menuSelected != null) {
            menuSelected.OnMenuSelected(items[e.Position]);
          }
        };
      }

How it works...

A Fragment element represents a behaviour or section of the user interface in an activity that can be reused across multiple activities and combined with other fragments. Fragments can be viewed as a subactivity that is semi-self-contained and has its own lifecycle.

Fragments allow us to create more dynamic and more flexible interfaces. They can be swapped and moved at runtime, without having to manage complex view hierarchies. They should be designed as a modular component, without directly manipulating the activity or other fragments. This makes them easier to reuse and maintain.

Note

The activity containing the fragments needs to inherit from AppCompatActivity when supporting Android versions below version 3.0.

As a fragment is usually used as part of the user interface with a layout, the interface can be inflated or created in the OnCreateView() method of the fragment. This method should return the view that is the root of the fragment's view hierarchy.

Note

A subclass of ListFragment does not need to implement the OnCreateView() method as it automatically has a ListView instance.

The OnCreateView() method has arguments that provide access to the view that is going to be used as a parent as well as the Bundle type that contains saved data from the previous instance of this fragment.

Tip

Fragments may be destroyed and re-created during the lifetime of a single activity.

Fragments can be added to the activity either with code using fragment transactions or by using the XML layout. In this recipe, we will look at the XML. Later, we will see how to use code for dynamic layouts. This is very similar to adding traditional views, except we use the <fragment> element and specify the type name in the name XML attribute, instead of using the type name as the element name.

Note

We can access fragments in the view hierarchy by making use of the FragmentManager instance and its FindFragmentById() method.

If a fragment is added to an activity layout by defining the fragment in the layout XML file, the fragment cannot be removed at runtime.

If a fragment wishes to communicate with the activity, an interface is used. This interface is provided by the fragment and implemented by the activity. The fragment can then capture a reference to the activity in the OnAttach() method—which will have the implemented interface—and use that for communication. The fragment can then verify that the activity implements the interface and make a decision on what to do with it. Communication is performed by calling methods on the interface from the fragment.

Tip

Communication between fragments is done via the activity and should not be done directly.

See also

  • Preserving view and fragment state
  • Navigation between fragments
..................Content has been hidden....................

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