Action Bar Tabs Example

This example shows how to access an activity's action bar and select its tab navigation mode, adding tabs to the activity for selecting different items of content.

A screenshot of the application.

We import the classes and modules that will be needed by the application. The Window class is particularly relevant since we use a constant it defines to request access to the action bar feature. The Fragment class is also notable because we use it to implement components within the application.

from java.lang import String
from android.app import Activity, ActionBar, Context, Fragment, FragmentTransaction
from android.os import Bundle
from android.view import LayoutInflater, View, ViewGroup, Window
from android.widget import FrameLayout, TextView

We also import the R object from the special app_resources module that is created by the build script. This provides constants that we use to refer to resources bundled in the application's package.

import android.R

We define a class based on the standard Activity class. This represents the application, and will be used to present a graphical interface to the user.

class ActionBarTabsActivity(Activity):

    __interfaces__ = [ActionBar.TabListener]

We declare that the class implements the ActionBar.TabListener interface. Implementing this interface involves implementing the three methods defined at the end of this class.

The initialisation method simply calls the corresponding base class method to properly initialise the activity.

    def __init__(self):
    
        Activity.__init__(self)

Similarly, the onCreate method calls the onCreate method of the base class to help set up the activity before creating a user interface.

    @args(void, [Bundle])
    def onCreate(self, bundle):
    
        Activity.onCreate(self, bundle)

We obtain the window shown by the activity and use its requestFeature method to request an action bar.

        window = self.getWindow()
        window.requestFeature(Window.FEATURE_ACTION_BAR)
        
        # This is needed to ensure that tab titles are visible.
        self.setTheme(android.R.style.Theme_DeviceDefault)

We create a FrameLayout to use as the activity's main view and give it an ID so that it can be referred to later. We also create a dictionary that we will use to manage the pieces of content that will be associated with each tab. The FrameLayout needs to be created before any tabs are added to the action bar since it is referred to in the tab handling methods.

        self.container = FrameLayout(self)
        self.container.setId(0x1234)
        self.fragments = {}

Having requested an action bar feature, we attempt to obtain its corresponding object. If one exists, we set its title and navigation mode.

        bar = self.getActionBar()
        
        if bar != None:
            bar.setTitle("Action Bar Tabs")
            bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS)

We add two tabs to the action bar, creating fragments that we associate with each tab using the dictionary created above. The TextViewFragment class is a custom Fragment that we define later.

            tab = bar.newTab()
            tab.setText("Tab 1")
            fragment = TextViewFragment("Hello world!", self)
            tab.setTabListener(self)
            self.fragments[tab] = fragment
            bar.addTab(tab)

Each tab is assigned a listener object which, in this example, is the activity itself. We define three methods below to handle user interactions with the tabs.

            tab = bar.newTab()
            tab.setText("Tab 2")
            fragment = TextViewFragment("This view is in another fragment.", self)
            tab.setTabListener(self)
            self.fragments[tab] = fragment
            bar.addTab(tab)
        
        self.setContentView(self.container)

The three methods that implement the ActionBar.TabListener interface are defined below. When the user selects a tab, the onTabUnselected method is called with the current tab, then the onTabSelected method is called with the new tab.

The onTabSelected method handles the process of adding the relevant Fragment to the FrameLayout created above, using the supplied FragmentTransaction object. We use the tab specified to retrieve the fragment from the dictionary of fragments and call the appropriate method of the transaction to make it visible.

    @args(void, [ActionBar.Tab, FragmentTransaction])
    def onTabSelected(self, tab, transaction):
    
        fragment = self.fragments[tab]
        transaction.add(self.container.getId(), fragment)

The onTabUnselected method handles the removal of the fragment associated with the previously selected tab in a similar way to the above method, calling the transaction's remove method to make way for the fragment for the newly selected tab.

    @args(void, [ActionBar.Tab, FragmentTransaction])
    def onTabUnselected(self, tab, transaction):
    
        fragment = self.fragments[tab]
        transaction.remove(fragment)

The onTabReselected method can be used to perform operations on the currently visible fragment when the current tab is selected. In this example we are not interested in doing anything with the fragment but must implement this method in any case.

    @args(void, [ActionBar.Tab, FragmentTransaction])
    def onTabReselected(self, tab, ft):
    
        pass

We define a custom class derived from the standard Fragment class. This is used to create user interface elements in response to transactions, as used by the ActionBar.TabListener interface. Instances of this class will create TextView objects on demand.

class TextViewFragment(Fragment):

    @args(void, [String, Context])
    def __init__(self, text, context):
    
        Fragment.__init__(self)
        self.text = text
        self.context = context

The initialisation method accepts parameters that specify some text to be used when setting up a TextView and the context in which to create each TextView. These are stored as instance attributes. The corresponding base class method is also called.

The onCreateView method is called when the fragment needs to supply a view for another component. In this example, we simply create a TextView using the context and text stored in the fragment and return it to the caller.

    @args(View, [LayoutInflater, ViewGroup, Bundle])
    def onCreateView(self, inflater, container, savedInstanceState):
    
        textView = TextView(self.context)
        textView.setText(self.text)
        return textView

Files