Creating and Managing Overflow Menus on Android with Kotlin

From Techotopia
Revision as of 18:28, 26 November 2017 by Neil (Talk | contribs) (Creating Checkable Item Groups)

Jump to: navigation, search

An area of user interface design that has not yet been covered in this book relates to the concept of menus within an Android application. Menus provide a mechanism for offering additional choices to the user beyond the view components that are present in the user interface layout. While there are a number of different menu systems available to the Android application developer, this chapter will focus on the more commonly used Overflow menu. The chapter will cover the creation of menus both manually via XML and visually using the Android Studio Layout Editor tool.


Contents


The Overflow Menu

The overflow menu (also referred to as the options menu) is a menu that is accessible to the user from the device display and allows the developer to include other application options beyond those included in the user interface of the application. The location of the overflow menu is dependent upon the version of Android that is running on the device. With the Android 4.0 release and later, the overflow menu button is located in the top right-hand corner (Figure 38-1) in the action toolbar represented by the stack of three squares:


[[File:]]

Creating an Overflow Menu

The items in a menu can be declared within an XML file, which is then inflated and displayed to the user on demand. This involves the use of the <menu> element, containing an <item> sub-element for each menu item. The following XML, for example, defines a menu consisting of two menu items relating to color choices:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=
           ".MenuExampleActivity" >
    <item
        android:id="@+id/menu_red"
        android:orderInCategory="1"
        app:showAsAction="never"
        android:title="@string/red_string"/>
         <item
        android:id="@+id/menu_green"
        android:orderInCategory="2"
        app:showAsAction="never"
        android:title="@string/green_string"/>
</menu>

In the above XML, the android:orderInCategory property dictates the order in which the menu items will appear within the menu when it is displayed. The app:showAsAction property, on the other hand, controls the conditions under which the corresponding item appears as an item within the action bar itself. If set to if Room, for example, the item will appear in the action bar if there is enough room. Figure 38-2 shows the effect of setting this property to ifRoom for both menu items:


[[File:]]


This property should be used sparingly to avoid over cluttering the action bar. By default, a menu XML file is created by Android Studio when a new Android application project is created. This file is located in the app -> res -> menu project folder and contains a single menu item entitled “Settings”:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" 
    tools:context=".MainActivity">
       <item android:id="@+id/action_settings" 
            android:title="@string/action_settings"
            android:orderInCategory="100" 
            app:showAsAction="never" />
</menu>

This menu is already configured to be displayed when the user selects the overflow menu on the user interface when the app is running, so simply modify this one to meet your needs.


Displaying an Overflow Menu

An overflow menu is created by overriding the onCreateOptionsMenu() method of the corresponding activity and then inflating the menu’s XML file. For example, the following code creates the menu contained within a menu XML file named menu_menu_example:

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    menuInflater.inflate(R.menu.menu_menu_example, menu)
    return true
}

As with the menu XML file, Android Studio will already have overridden this method in the main activity of a newly created Android application project. In the event that an overflow menu is not required in your activity, either remove or comment out this method.

Responding to Menu Item Selections

Once a menu has been implemented, the question arises as to how the application receives notification when the user makes menu item selections. All that an activity needs to do to receive menu selection notifications is to override the onOptionsItemSelected() method. Passed as an argument to this method is a reference to the selected menu item. The getItemId() method may then be called on the item to obtain the ID which may, in turn, be used to identify which item was selected. For example:

override fun onOptionsItemSelected(item: MenuItem): Boolean {
 
    when (item.itemId) {
        R.id.menu_red -> {
            return true
        }
        R.id.menu_green -> {
            return true
        }
        else -> return super.onOptionsItemSelected(item)
    }
 
}

Creating Checkable Item Groups

In addition to configuring independent menu items, it is also possible to create groups of menu items. This is of particular use when creating checkable menu items whereby only one out of a number of choices can be selected at any one time. Menu items can be assigned to a group by wrapping them in the <group> tag. The group is declared as checkable using the android:checkableBehavior property, setting the value to either single, all or none. The following XML declares that two menu items make up a group wherein only one item may be selected at any given time:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <group android:checkableBehavior="single">
        <item
            android:id="@+id/menu_red"
            android:title="@string/red_string"/>
        <item
            android:id="@+id/menu_green"
            android:title="@string/green_string"/>
    </group>
</menu>

When a menu group is configured to be checkable, a small circle appears next to the item in the menu as illustrated in Figure 38-3. It is important to be aware that the setting and unsetting of this indicator does not take place automatically. It is, therefore, the responsibility of the application to check and uncheck the menu item.


[[File:]]


Continuing the color example used previously in this chapter, this would be implemented as follows:

override fun onOptionsItemSelected(item: MenuItem): Boolean {
 
    when (item.itemId) {
        R.id.menu_red -> {
            if (item.isChecked)
                item.isChecked = false
            else
                item.isChecked = true
            return true
        }
        R.id.menu_green -> {
            if (item.isChecked)
                item.isChecked = false
            else
                item.isChecked = true
            return true
        }
        else -> return super.onOptionsItemSelected(item)
    }
}

Menus and the Android Studio Menu Editor

Android Studio allows menus to be designed visually simply by loading the menu resource file into the Menu Editor tool, dragging and dropping menu elements from a palette and setting properties. This considerably eases the menu design process, though it is important to be aware that it is still necessary to write the code in the onOptionsItemSelected() method to implement the menu behavior.

To visually design a menu, locate the menu resource file and double-click on it to load it into the Menu Editor tool. Figure 38-4, for example, shows the default menu resource file for a basic activity loaded into the Menu Editor:


[[File:]]


The palette (A) contains items that can be added to the menu contained in the design area (C). The Component Tree (B) is a useful tool for identifying the hierarchical structure of the menu. The Attributes panel (D) contains a subset of common attributes for the currently selected item. The view all attributes link (E) may be used to access the full list of attributes.

New elements may be added to the menu by dragging and dropping objects either onto the layout canvas or the Component Tree. When working with menus in the Layout Editor tool, it will sometimes be easier to drop the items onto the Component Tree since this provides greater control over where the item is placed within the tree. This is of particular use, for example, when adding items to a group.

Although the Menu Editor provides a visual approach to constructing menus, the underlying menu is still stored in XML format which may be viewed and edited manually by switching from Design to Text mode using the tab marked F in the above figure.

Creating the Example Project

To see the overflow menu in action, create a new project in Android Studio, entering MenuExample into the Application name field and ebookfrenzy.com as the Company Domain setting before clicking on the Next button.

On the form factors screen, enable the Phone and Tablet option and set the minimum SDK setting to API 14: Android 4.0 (IceCreamSandwich). Continue to proceed through the screens, requesting the creation of a basic activity named MenuExampleActivity with a corresponding layout file named activity_menu_example.

When the project has been created, navigate to the app -> res -> layout folder in the Project tool window and double-click on the content_menu_example.xml file to load it into the Android Studio Menu Editor tool. Switch the tool to Design mode, select the ConstraintLayout from the Component Tree panel and enter layoutView into the ID field of the Attributes panel.

Designing the Menu

Within the Project tool window, locate the project’s app -> res -> menu -> menu_menu_example.xml file and double-click on it to load it into the Layout Editor tool. Select and delete the default Settings menu item added by Android Studio so that the menu currently has no items.

From the palette, click and drag a menu group object onto the title bar of the layout canvas as highlighted in Figure 38-5:


[[File:]]


Although the group item has been added, it will be invisible within the layout. To verify the presence of the element, refer to the Component Tree panel where the group will be listed as a child of the menu:


[[File:]]


Select the group entry in the Component Tree and, referring to the Attributes panel, set the checkableBehavior property to single so that only one group menu item can be selected at any one time:


[[File:]]


Next, drag four Menu Item elements from the palette and drop them onto the group element in the Component Tree. Select the first item and use the Attributes panel to change the title to “Red” and the ID to menu_red:


[[File:]]


Repeat these steps for the remaining three menu items setting the titles to “Green”, “Yellow” and “Blue” with matching IDs of menu_green, menu_yellow and menu_blue. Use the warning buttons to the right of the menu items in the Component Tree panel to extract the strings to resources:


[[File:]]


On completion of these steps, the menu layout should match that shown in Figure 38-10 below:


[[File:]]


Switch the Layout Editor tool to Text mode and review the XML representation of the menu which should match the following listing:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.ebookfrenzy.menuexample.MenuExampleActivity">
 
    <group android:checkableBehavior="single">
        <item android:title="@string/red_string"
            android:id="@+id/menu_red" />
        <item android:title="@string/green_string"
            android:id="@+id/menu_green" />
        <item android:title="@string/yellow_string"
            android:id="@+id/menu_yellow" />
        <item android:title="@string/blue_string"
            android:id="@+id/menu_blue" />
    </group>
</menu>

Modifying the onOptionsItemSelected() Method

When items are selected from the menu, the overridden onOptionsItemsSelected() method of the application’s activity will be called. The role of this method will be to identify which item was selected and change the background color of the layout view to the corresponding color. Locate and double-click on the app -> java -> com.ebookfrenzy.menuexample -> MenuExampleActivity file and modify the method as follows:

package com.ebookfrenzy.menuexample
 
import android.os.Bundle
import android.support.constraint.ConstraintLayout
import android.support.design.widget.Snackbar
import android.support.v7.app.AppCompatActivity
import android.view.Menu
import android.view.MenuItem
 
import kotlinx.android.synthetic.main.activity_menu_example.*
import kotlinx.android.synthetic.main.content_menu_example.*
 
class MenuExampleActivity : AppCompatActivity() {
.
.
.
    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        // Inflate the menu; this adds items to the action bar if it is present.
        menuInflater.inflate(R.menu.menu_menu_example, menu)
        return true
    }
 
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
 
        when (item.itemId) {
            R.id.menu_red -> {
                if (item.isChecked)
                    item.isChecked = false
                else
                    item.isChecked = true
                layoutView.setBackgroundColor(android.graphics.Color.RED)
                return true
            }
            R.id.menu_green -> {
                if (item.isChecked)
                    item.isChecked = false
                else
                    item.isChecked = true
                layoutView.setBackgroundColor(android.graphics.Color.GREEN)
                return true
            }
            R.id.menu_yellow -> {
                if (item.isChecked)
                    item.isChecked = false
                else
                    item.isChecked = true
                layoutView.setBackgroundColor(android.graphics.Color.YELLOW)
                return true
            }
            R.id.menu_blue -> {
                if (item.isChecked)
                    item.isChecked = false
                else
                    item.isChecked = true
                layoutView.setBackgroundColor(android.graphics.Color.BLUE)
                return true
            }
            else -> return super.onOptionsItemSelected(item)
        }
 
    }
.
.
}

Testing the Application

Build and run the application on either an emulator or physical Android device. Using the overflow menu, select menu items and verify that the layout background color changes appropriately. Note that the currently selected color is displayed as the checked item in the menu.


[[File:]]

Summary

The Android overflow menu is accessed from the far right of the actions toolbar at the top of the display of the running app. This menu provides a location for applications to provide additional options to the user.

The structure of the menu is most easily defined within an XML file and the application activity receives notifications of menu item selections by overriding and implementing the onOptionsItemSelected() method.