The menu control of Android is an interesting example for how the developers of the system react on experiences with the usage of the system.
In the beginning - before 3.0 - the options menu was regarded so important, that there was given a seperate key for it.
The menu was realized as a pure popup menu.
Even the name speaks for the purpose of the menu as editing settings of the application.
Indeed it happened that many applications mis-used the options menu to realize navigation.
With 3.0 the concept was re-worked. Surely it was taken into account, that the purpose of this version was mainly to support tablets and so there was enough space on the screen. The action bar as a totally new element was introduced and the options menu was integrated in this component. The action bar as a given part by default is always visible on the screen (though it may be deactivated). Since Android 4.0 the action bar is also part of the smartphone variant of the operating system. The menu key is not longer a required element of a smartphone.
The action bar is mainly devided into 4 parts ("app icon", "view control", "action buttons" and "action overflow"). The visible appearance is configurable and depends on the space available on the actual device. So the "view control" may be shown in an additional row below the main action bar (as visible in the image) or the "action buttons" may use the space on the bottom of the screen.
The "app icon" (left in the image) serves to identify the running application. It can also be used to navigate "home" or "back".
The "view control" is used to navigate in between the application, for example to activate different pages (fragments) of an activity in form of tabs.
The "action buttons" (right in the image) get close to the options menu used so far. They serve to call context sensitive additional actions. For actions used regularly this can be done directly by icon in this area, less reqularly used actions can be placed in the "action overflow" part. If there is a menu key on the device, the "action overflow" is activated by this key, otherwise there will be shown an appropriate selection list.
Not only relating to content and to handling the actions buttons of Android 3.0 replace the options menu of the earlier versions, but also from the programmers view. The transfer is very transparent.
With 2.x an options menu could be simply declared as following:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/mainMenuItem" android:title="@string/main" />
<item android:id="@+id/layoutDemoMenuItem" android:title="@string/layoutDemo" />
<item android:id="@+id/layoutDemo2MenuItem" android:title="@string/layoutDemo" />
<item android:id="@+id/fragmentMenuItem" android:title="@string/fragment" />
</menu>
Methods to add the options menu and to react on the selection of an item are overwritten on the Activity. In this case in form of a BaseActivity, where all the Acivity-Classes that use the options menu may be derived.
public class BaseActivity extends Activity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.mainMenuItem:
case android.R.id.home:
Log.v(getLocalClassName(), "call main");
Intent intent = new Intent(this, Workshop4Activity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
break;
case R.id.fragmentMenuItem:
Log.v(getLocalClassName(), "call fragment");
startActivity(new Intent(this, FragmentActivity.class));
break;
case R.id.layoutDemoMenuItem:
Log.v(getLocalClassName(), "call layoutDemo");
startActivity(new Intent(this, LayoutDemoActivity.class));
break;
case R.id.layoutDemo2MenuItem:
Log.v(getLocalClassName(), "call layoutDemo");
startActivity(new Intent(this, LayoutDemoActivity2.class));
break;
}
return true;
}
}
That's all for the trivial case.
To make the entries of the options menu visible in the action bar on Android 4.0, the corresponding entry of the XML file is given an attribute "android:showAsAction". Possible values are "never", "always", "ifRoom", "withText" and "collapseActionView". Those values may be - if it makes sense - combined with "|".
That's all so far, the BaseActivity does not need to be changed.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/mainMenuItem" android:title="@string/main"
android:showAsAction="ifRoom|withText" />
<item android:id="@+id/layoutDemoMenuItem" android:title="@string/layoutDemo"
android:showAsAction="always" />
<item android:id="@+id/layoutDemo2MenuItem" android:title="@string/layoutDemo"
android:showAsAction="ifRoom" />
<item android:id="@+id/fragmentMenuItem" android:title="@string/fragment"
android:showAsAction="ifRoom" />
</menu>
It is possible to replace the "action buttons" by more complicated controls. The possibilities surely are limited by the rare available space. An ActionProvider may replace the complete logic. "collapseActionView" allows a "short view", from which by click a more detailed view is opened.
The navigation in the "view control" part of the action bar also is not very complicated. The developer documentation describes this very useful (http://developer.android.com/guide/topics/ui/actionbar.html). There is for the case, that the pages to navigate to are realized as Fragments, simply implemented an ActionBar.TabListener. This one instantiiates the concrete Fragments as needed. Each "view control" entry of the action bar is linked with the corresponding Listener. At last only the NavigationMode of the action bar has to be set to "NAVIGATION_MODE_TABS" - in the onCreate-method of the Activity. The ContentView of the Activity has not to be set, only the default container is used. It also is relatively simple, to use a Spinner-control instead of a tab navigation. The elements of the list are defined in an array ressource and the selection of the elements is realized by a SpinnerAdapter and an OnNavigationListener.