Android – with Eclipse v3.5 IDE, App’s Menu == adding a “menu” at the bottom of the App screen

An easy means of navigation within an application’s screens, or to access additional features and settings without losing of focus from the main screen of an application is by using menus.

screencap10a  screencap11a

To look closer, it’s the [MENU] button of the smart phone case (not just part of a touch screen); it provides consistent means of accessing options, settings, and common properties of many of the Smartphone apps. Usually, it’s just one or two rows; and no more than three items per row.

Here, the system menu is shown, which allows adding shortcuts or applications on the main Android screen. At the system menu we also can modify the wallpaper on the main screen, or to go into the settings, notifications, and/or for a quick access to searching both on your handheld or on the web. The Clock shown in this screen capture was added to the main Android screen by using this menu, and then “Add” to find “Widgets” from which “Analog Clock” was selected.

Adding a menu feature into our own application requires a combination of Java code changes, XML settings, and modifications to the Android Manifest file to apply to the screens of an Application.

screencap21a Simulator menu-shot

Clicking on one of the menu options starts a new activity and brings up a new screen. In this tutorial, we will add a menu to an existing application (activity). That menu will have a single option — to display an "about" screen. We will start at the end (the display) and work toward the beginning (the menu click) so references are defined when we need them.

An outline of the steps we will take:

1. Create the XML for the "about" screen with text that talks "about" application.

2. Create a new activity class in java code which will display the "about" screen.

3. Add this new activity to the manifest.

4. Define the menu in XML, identifying the option(s) to be available.

5. Modify the existing activity to include code to reference the menu and direct the

actions which occur when a menu option is selected.

 

THE “ABOUT” ACTIVITY

A new XML file is created in the res/layout directory to describe the ABOUT screen . In our case, this is a very simple screen. It has one TextView that contains all the text that we want to display. We have placed this TextView with a ScrollView so that the text will scroll if it exceeds the space available on the screen. Note that line breaks included in the text will appear on the screen; without line breaks the text will wrap.

res/layout/about.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android=
http://schemas.android.com/apk/res/android
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dip">

<TextView
android:id="@+id/about_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="19sp" android:textColor="#ffffff"
android:text="FuelTrak is an application for tracking the MPG of your vehicle by calculating the gallons purchased and the number of miles driven. Multiple vehicles are supported. The inputs are maintained as a log to record the efficiency over time indicating things like servicing indicators and overall gasoline consumption and driving records for the months and years you drive your car." />
</ScrollView>

A new java file is created in the src directory to show the ABOUT screen. Again, this is very simple. The class ABOUT is defined as an extension of the ACTIVITY class, and upon creation the activity will set the context view to the about screen we defined above.

src/project/about.java

package com.donovanden.refuel;
import android.app.Activity;
import android.os.Bundle;

public class About extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.about);
    }
}

This new activity must be included in the Manifest, so it is known to the project.

Android/Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android=
http://schemas.android.com/apk/res/android
package="com.donovanden.refuel"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon"
android:label="@string/app_name">
<activity android:name=".Combined"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".About"
android:label="About"
android:theme="@android:style/Theme.Dialog">
</activity>
</application>
<uses-sdk android:minSdkVersion="7" />
</manifest>

ADDING THE MENU

Now we are ready to define the menu itself. This is done with a new XML file in the res/menu directory. This is not a regular layout file, but an XML file which has one ITEM for each option on the menu. We only define one which will display the title "About" and is referenced by R.id.about_menuitem.

res/menu/menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"&gt;
<item android:id="@+id/about_menuitem" android:title="About"></item>
</menu>

Finally, we add code to the activity which supports the menu. First we add code which creates the menu and "inflates" the display at the bottom of the screen to show the menu options. To use this code, you will need to import three classes.

src/project/main.java

import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;

public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu, menu);
    return true;
}

The resources in the R. reference above are key – specified in the hierarchy which Eclipse is managing for us – the orange “.menu” references a folder we are keeping menu specifications in, and the purple “.menu” is for the file named “menu.xml”. From the Android library, the inflate function needs these xml definitions, and expects a “menu” parameter which is the location of the structures we used for the menu definition. The second parameter to the inflate function specifies where that memory is located.

It remains a mystery to us the purpose of the incoming parameter named "menu" in this method. It appears to be something internal. When the menu is called (created) by pressing the MENU key, the inflater builds the menu screen based on our items specified in R.menu.menu (res/menu/menu.xml).

Then we add code to link a click on the menu option to our desired action — the display of the about screen (by starting the About activity).

src/project/main.java

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.about_menuitem:
        startActivity(new Intent(this, About.class));
    }
    return true;
}

This method detects clicks on the menu items. We determine which item was selected by comparing the MenuItem (passed as a parameter to the method) to the item id’s that we established in res/menu/menu/xml. Of course, in the present case there is only one item, but this "switch" code allows for easy upgrade for additional items. When the user clicks on the ABOUT button, the About activity (as defined in the manifest) is initiated.

ADDING SETTINGS

Now let’s expand our menu to include another item – we will allow the user to adjust "settings" for the application. Android has a special class to handle these settings called PreferenceActivity — and each setting is called a "preference"..

Again we start by building the screen which is used to set the preferences. Instead of building a screen layout, this involves an xml file this lists each preference and is stored in res/xml directory

res/xml/settings.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"&gt;
<CheckBoxPreference
android:key="fulltank"
android:title="fulltank title"
android:summary="fulltank summary"
android:defaultValue="true" />
<CheckBoxPreference
android:key="units"
android:defaultValue="true"
android:summary="use Gallons and Miles"
android:title="Imperial units"/>
<CheckBoxPreference
android:key="other"
android:title="other title"
android:summary="other summary"
android:defaultValue="false" />
</PreferenceScreen>

Now create the java file for the class activity which displays these settings. Note that this activity does not use setContextView, but addPreferencesFromResource (a built in part of PreferenceActivity that does a lot of the work for us).

src/project/Preferences.java

package com.donovanden.project;
import android.os.Bundle;
import android.preference.PreferenceActivity;
public class Preferences extends PreferenceActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        addPreferencesFromResource(R.xml.settings);
    }
}

This new activity must be included in the Manifest.

Android/Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android=
http://schemas.android.com/apk/res/android
package="com.donovanden.refuel"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon"
android:label="@string/app_name">
<activity android:name=".Combined"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".About"
android:label="About"
android:theme="@android:style/Theme.Dialog">
</activity>
<activity android:name=".Preferences"
android:label="Settings ">
</activity>
</application>
<uses-sdk android:minSdkVersion="7" />

 

Add an new item to the menu for navigation to the new settings screen

res/menu/menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"&gt;
<item android:id="@+id/about_menuitem" android:title="About" />
<item android:id="@+id/settings_menuitem" android:title="Settings" />
</menu>

The menu code has already been added to our base activity; we only need to update the coded action on the click (when users selects a menu option).

src/project/main.java

public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.about_menuitem:
        startActivity(new Intent(this, About.class));
       
case R.id.settings_menuitem:
        startActivity(new Intent(this, Preferences.class));
    }
    return true;
}

 

 

Adding the class definition for the references in is easiest in a separate .java file.

For example, the line of Java code:

startActivity(new Intent(this, Preferences.class));

has the reference to an instance of the Preferences.class, which is shown here:

/***
*   My preferences:
*   March 18, 2010
***/
package com.example.FuelTracker;

import android.os.Bundle;
import android.preference.PreferenceActivity;

public class Preferences extends PreferenceActivity {
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      addPreferencesFromResource(R.xml.settings);
   }
}

NOTE:  It’s NOT important that Preferences is called Preferences, but it is inheriting PreferenceActivity (that name, IS IMPORTANT).

We are creating a new activity – this has an associated Linux process behind the scenes, but what is important is that when it’s started, the menu inherits the appearance (usually) and the behaviours of a menu (from it’s parent class: PreferenceActivity). This includes the popping to the front at the bottom of the Android platform’s screen, and allowing the user to select one of these defined items from the menu.xml declaration. When selected, the activity executes – and, then terminates. (NEED TO CHECK, does it terminate, does it?).

The key statement here, as a function which calls “addPreferencesFromResource” and pass it the XML definitions in “settings”.

Refer to the res\xml\settings.xml file:

<PreferenceScreen
   xmlns:android="
http://schemas.android.com/apk/res/android">
   <CheckBoxPreference
      android:key="fulltank"
      android:title="fulltank title"
      android:summary="fulltank summary"
      android:defaultValue="true" />
   <CheckBoxPreference
      android:key="units"
      android:title="Imperial units title"
      android:summary="Imperial system, meaning Gallons and Miles"
      android:defaultValue="true" />
   <CheckBoxPreference
      android:key="other"
      android:title="other title"
      android:summary="other summary"
      android:defaultValue="false" />
</PreferenceScreen>

Notice in the above XML code, we’ve listed some of the extra directives; for example: “defaultValue” is either set to “true” or “false” to predetermine the setting the first time that the preference screen appears.  What may not be aparrent is that the title or summary values may be a string reference to an associated XML file.  But, for this first example it seems easier to just enter the text definitions directly.  If you use the Eclipse plug-in, these string value references to the strings.xml file in the values folder of the project are the way it’s usually defined.

The graphic version of these entries can also be used (screen shot, from V3.5 Eclipse, with Android Plug-in)

screencap17a Menu settings form closeup

When (I’d say “if”, except that it’s a pretty much CERTAINTY that you’ll see this occur) you get an error, which results in an unexpected termination of the program… there is NOT a lot of hints provided to describe the problem.  It may be that you are starting an activity which doesn’t have a class associated with it; or your code to create that class doesn’t exist, or has errors in the logic.   But, backing up to the working version (comment out the lines which start the activity) may be helpful.

screencap15a stopped unexpectedly

To address this, the likely oversight in adding menu code into your applications is resolved when you update the Manifest.

 screencap19b Manifest onNavigator closeup screencap19c Manifest xml definitions closeup

To look more closely at the lines in the manifest which are important for the menu:

For each added activity, a name is specified (and, inferred, there’s a source file and class defined for it).

<activity android:name=".Preferences"
      android:label="Settings inManifest">
</activity>

This establishes the association of the “.Preferences” class, with this activity which was called above from the main “OnCreateMenu” function.

 

 

 

 

Revisiting:

In the XML file for the menu, when we specify a string value for the title it looked like:

<item android:id="@+id/settings"
    . . .
    android:title="Settings"
    .

We notice the more official approach is to use a reference to the strings file.

<item android:id="@+id/settings"
    .
    android:title="@string/settings_label"

These indirect references to the string’s value is supported by the Eclipse v3.5 IDE when you have the Android plug-in.  The “keyboard shortcut” and other definitions should similarly be replaced with the strings;  we will presume that it’s better especially for internationalization, and likely other facilities within the Android SDK and the IDE to be using a centralized location for all these values.   For now, the direct text entry seems easier to a first time experience. The same case would be made for the “settings.xml” file.

About these ads
Explore posts in the same categories: Android, SDK, Java, Google

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s


Follow

Get every new post delivered to your Inbox.

%d bloggers like this: