RE: Walkthrough – Creating a tabbed UI with TabHost

This article will walk through creating a tabbed UI in Xamarin.Android using the TabHost API. This is an older API that is available in all versions of Android. This example will create an application with three tabs, with the logic for each tab being encapsulated in an Activity. The following screenshot is an example of the application that we will create:

Creating the Application

    1. Download and unzip the project . This project serves as the starting point for our application and contains some images. This is a Xamarin.Android Application project that you would get from File > New > New Solution and accept the Android Application template. If you examine this project, you will see that we’ve already created the drawable resources for the tab icons.
    2. First let’s update the layout file Resources/Layout/Main.axml that will host the tabs. Edit file Resources/Layout/Main.axml file and insert the following XML:
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@android:id/tabhost"
         android:layout_width="fill_parent"
         android:layout_height="fill_parent">
    <LinearLayout
            android:orientation="vertical"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:padding="5dp">
        <TabWidget
                android:id="@android:id/tabs"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content" />
        <FrameLayout
                android:id="@android:id/tabcontent"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:padding="5dp" />
    </LinearLayout>
</TabHost>

The following screenshot shows the layout in the Xamarin Designer:

The TabHost must have two child views inside it: a TabWidget and a FrameLayout. To position the TabWidget and FrameLayout vertically inside the TabHost, a LinearLayout is used. The FrameLayout is where the content for each tab goes, which is empty because the TabHost will automatically embed each Activity at runtime.

There are several rules that must be observed when it comes to creating the layout for tabbed user interfaces:

  • The TabHost must have the id @android:id/tabhost.
  • The TabWidget must have the id @android:id/tabs.
  • The FrameLayout must have the id @android:id/tabcontent.
  • TabHost requires any activity it manages to inherit from TabActivity. Therefore, it is important to subclass TabActivity here – a regular Activity will not work.

    Edit the file MainActivity.cs so that the class MainActivity subclasses TabActivity as shown in the following code snippet:

[Activity (Label = "@string/app_name", MainLauncher = true, Icon="@drawable/ic_launcher")]
public class MainActivity : TabActivity
{
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
        SetContentView(Resource.Layout.Main);
    }
}
  • Create four separate Activity classes in your project: MyScheduleActivity, SessionsActivity, SpeakersActivity, and WhatsOnActivity. Each activity will make up the UI of a tab. For now these Activities will be a stub that displays a TextView with a simple message. Edit the code in each activity to contain the following OnCreate implementation:
[Activity]
public class MyScheduleActivity : Activity
{
    protected override void OnCreate (Bundle savedInstanceState)
    {
        base.OnCreate (savedInstanceState);
        TextView textview = new TextView (this);
        textview.Text = "This is the My Schedule tab";
        SetContentView (textview);
    }
}

Notice that the above code doesn’t use a layout file. It just creates a TextView with some text, and sets that TextView as the content view. Duplicate this for each of the remaining three activities.

  • Next we will assign the icons to each tab. Each tab requires two icons – one for the selected state and one for the unselected state. An example of these two different icons can be seen in the following two images:

  

The necessary icons for this application have already been added to the sample project.

We will assign the drawable resources to the icon tabs by defining a State-List Drawable. State-list drawables are a special drawable resources that are defined in XML and allow you to specify different images that are specific to that item’s state. In this example there is one image that is used when a tab is selected, and another that is used when the tab is not selected. To save you time, the necessary state-list drawables have been added to the project. The following table shows the files and the XML they contain:

State-List Drawable File XML
ic_tab_my_schedule.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_tab_whats_on_selected"
          android:state_selected="true"/>
    <item android:drawable="@drawable/ic_tab_whats_on_unselected"/>
</selector>
ic_tab_sessions.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_tab_sessions_selected"
          android:state_selected="true"/>
    <item android:drawable="@drawable/ic_tab_sessions_unselected"/>
</selector>
ic_tab_speakers.xml
<?xml version="1.0" encoding="utf-8"?>
                <selector xmlns:android="http://schemas.android.com/apk/res/android">
                    <item android:drawable="@drawable/ic_tab_speakers_selected"
                          android:state_selected="true"/>
                    <item android:drawable="@drawable/ic_tab_speakers_unselected"/>
                </selector>
ic_tab_whats_on.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_tab_whats_on_selected"
          android:state_selected="true"/>
    <item android:drawable="@drawable/ic_tab_whats_on_unselected"/>
</selector>
  • Tabs are added to the TabHost programmatically, which is a very repetitive task. To help with this, add the following method to the class MainActivity:
private void CreateTab(Type activityType, string tag, string label, int drawableId )
{
    var intent = new Intent(this, activityType);
    intent.AddFlags(ActivityFlags.NewTask);

    var spec = TabHost.NewTabSpec(tag);
    var drawableIcon = Resources.GetDrawable(drawableId);
    spec.SetIndicator(label, drawableIcon);
    spec.SetContent(intent);

    TabHost.AddTab(spec);
}

Each tab in the TabHost is represented by an instance of the of the TabHost.TabSpec class. This instance contains the meta-data necessary to render the tab, specifically:

  • Text and Icon – To be displayed in the TabWidget.
  • Tab Content – This may be either an Activity or a View and is displayed when the tab is selected.
  • Unique Tag – Each tab must have a unique tag assigned to it.

We must add a TabHost.TabSpec instance for each tab in our application. Lets do that in the next step.

  • Update the method OnCreate in MainActivity so that it resembles the following code:
  1. protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
        SetContentView(Resource.Layout.Main);
    
        CreateTab(typeof(WhatsOnActivity), "whats_on", "What's On", Resource.Drawable.ic_tab_whats_on);
        CreateTab(typeof(SpeakersActivity), "speakers", "Speakers", Resource.Drawable.ic_tab_speakers);
        CreateTab(typeof(SessionsActivity), "sessions", "Sessions", Resource.Drawable.ic_tab_sessions);
        CreateTab(typeof(MyScheduleActivity), "my_schedule", "My Schedule", Resource.Drawable.ic_tab_my_schedule);
    }

  2. Run the application. Your application should look something like the following:

That’s it! We have created a tabbed application which gives the user an easy way navigate to different parts of an application

Summary

This chapter discussed tabbed layouts and guided you through process of creating a tabbed application. The walkthrough demonstrated how to use a TabActivity to inflate a layout file that hosting a TabHost and a TabWidget. The TabHost was then populated with a collection of TabHost.TabSpec objects which would be used by the TabHost at runtime to instantiate the activities that would be used in each tab.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s