Sometimes normal layouts aren't dynamic enough or we may have to reuse sections of the UI and its related code.
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.
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:
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"}); } }
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>
OnCreateView()
method:public class ContentFragment : Fragment { public override View OnCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.Inflate( Resource.Layout.ContentFragment, container, false); } }
public void Update(string text) { var textView = Activity.FindViewById<TextView> (Resource.Id.textView); textView.Text = string.Format( "You have selected '{0}'...", text); }
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>
SetContentView()
method:protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); SetContentView(Resource.Layout.Main); }
public interface IMenuSelected { void OnMenuSelected(string text); }
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); }
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; }
OnMenuSelected()
method of the activity:public override void OnStart() { // ... ListView.ItemClick += (sender, e) => { if (menuSelected != null) { menuSelected.OnMenuSelected(items[e.Position]); } }; }
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.
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.
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.
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.
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.