Android Menu Using Kotlin

Filed Under: Android

In this tutorial, we’ll be discussing and implement the Android Menu class in our android application using Kotlin.
We’ll see the different ways in which Menus can be displayed on the screen.

Android Menu

Menus are a UI component that is used to display a list of options to perform a quick action.
Menus in Android are largely divided into three different types:

  • Options Menu – These are the most common form of menus. They’re typically displayed in the Toolbar.
  • Context Menu – These are floating menus that are displayed when a user long clicks on the widget that’s ought to show the Menu
  • Popup Menu – These are displayed on the anchor point above or below the widget that is clicked.

Android Menus can be defined inside the resources folder.
Every menu is associated with an icon and a title along with an attribute: showAsAction.
android:orderInCategory attribute is used to set the order of the menu items in the menu. The highest order occupies the leftmost position. It accepts an integer value.

In the following section, we’ll be creating an Android Application Using Kotlin which will cover each of these menu types.

Project Structure

android-menu-project-structure

In the res folder create a new resource directory to hold menus.
In the new menu folder that gets created, create a menu resource layout file:

android-menu-resource-file

Code

The code for the menu_main.xml menu file is given below:


<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/agenda"
        android:icon="@android:drawable/ic_menu_agenda"
        android:orderInCategory="100"
        android:title="Agenda"
        app:showAsAction="never" />

    <item
        android:id="@+id/call"
        android:icon="@android:drawable/ic_menu_call"
        android:orderInCategory="100"
        android:title="Call"
        app:showAsAction="always" />


    <item
        android:id="@+id/add"
        android:icon="@android:drawable/ic_menu_add"
        android:orderInCategory="100"
        android:title="Add"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/compass"
        android:icon="@android:drawable/ic_menu_compass"
        android:orderInCategory="100"
        android:title="Compass"
        app:showAsAction="always" />

    <item
        android:id="@+id/day"
        android:orderInCategory="100"
        android:title="Day"
        app:showAsAction="always|withText" />


</menu>

ifRoom value indicates to show the menu icon only if there is space. This priority is the second lowest.
never value indicates that menu icon would not be shown at all in the Toolbar/Menu layout. It’ll reside in the overflow menu.
always indicates that the menu icon.
withText indicates that the menu text would be displayed.

We can club any two of the above values(clubbing never value doesn’t make sense!)

The code for the popup_menu.xml menu file is given below:


<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/one"
        android:title="One" />

    <item
        android:id="@+id/two"
        android:title="Two" />

    <item
        android:id="@+id/three"
        android:title="Three" />

</menu>

Menu Items can be grouped too. We can add a checkable behavior on the groups:
popup_menu_group.xml


<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group
        android:id="@+id/my_move"
        android:checkableBehavior="single">
        <item
            android:id="@+id/one"
            android:title="One" />

        <item
            android:id="@+id/two"
            android:title="Two" />

        <item
            android:id="@+id/three"
            android:title="Three" />
    </group>

    <group
        android:id="@+id/second"
        android:checkableBehavior="all">
        <item
            android:id="@+id/four"
            android:checked="true"
            android:title="Four" />

        <item
            android:id="@+id/five"
            android:title="Five" />

        <item
            android:id="@+id/six"
            android:title="Six" />
    </group>

</menu>

The code for the activity_main.xml layout file is given below:


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btnContextMenu"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Context Menu"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btnPopUpMenu"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="Popup Menu"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btnContextMenu" />

    <Button
        android:id="@+id/btnPopUpMenuGroup"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="Popup Menu Group"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btnPopUpMenu" />

</android.support.constraint.ConstraintLayout>

For the Options Menu two methods namely: onCreateOptionsMenu and onOptionsItemSelected need to be overridden. In the onCreateOptionsMenu we inflate the XML menu using the MenuInflater class.

ContextMenu is triggered on a particular view. We need to call registerForContextMenu on that view. This triggers onCreateContextMenu where we add MenuItems in the menu list.
onContextItemSelected is triggered when any ContextMenu is selected.

PopupMenu is created when any view is clicked. The PopMenu gets initialized there itself by inflating the menu resource file using the menuInflater. To display the PopupMenu we call the function show on the instance of it.

The code for the MainActivity.kt class is given below:


package com.journaldev.androidlymenus

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.*
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_main.*
import android.support.v7.widget.PopupMenu


class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        registerForContextMenu(btnContextMenu)

        btnContextMenu.setOnLongClickListener {
            openContextMenu(btnContextMenu)
            true
        }

        btnPopUpMenu.setOnClickListener {

            val popup = PopupMenu(this@MainActivity, btnPopUpMenu)
            //Inflating the Popup using xml file
            popup.menuInflater.inflate(R.menu.popup_menu, popup.menu)


            popup.setOnMenuItemClickListener({
                if (it.itemId == R.id.one) {
                    Toast.makeText(applicationContext, "One", Toast.LENGTH_SHORT).show()
                } else {
                    Toast.makeText(applicationContext, "None", Toast.LENGTH_SHORT).show()
                }
                true
            })

            popup.show()//showing popup menu

        }

        btnPopUpMenuGroup.setOnClickListener {

            val popup = PopupMenu(this@MainActivity, btnPopUpMenu)
            //Inflating the Popup using xml file
            popup.menuInflater.inflate(R.menu.popup_menu_group, popup.menu)


            popup.setOnMenuItemClickListener({
                if (it.itemId == R.id.four && it.isChecked) {
                    Toast.makeText(applicationContext, "Four. Was Checked", Toast.LENGTH_SHORT).show()
                } else {
                    Toast.makeText(applicationContext, it.title, Toast.LENGTH_SHORT).show()
                }
                true
            })
            popup.show()

        }
    }

    override fun onCreateContextMenu(menu: ContextMenu?, v: View?, menuInfo: ContextMenu.ContextMenuInfo?) {
        super.onCreateContextMenu(menu, v, menuInfo)
        menu?.setHeaderTitle("Context Menu")
        menu?.add(0, v?.id!!, 0, "Call")
        menu?.add(0, v?.id!!, 1, "SMS")
        menu?.add(1, v?.id!!, 0, "Search")

    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        val inflater = menuInflater
        inflater.inflate(R.menu.menu_main, menu)
        return true
    }

    override fun onContextItemSelected(item: MenuItem?): Boolean {

        when {
            item?.title == "Call" -> {
                Toast.makeText(applicationContext, "Call", Toast.LENGTH_LONG).show()
                return true
            }
            item?.title == "SMS" -> {
                Toast.makeText(applicationContext, "SMS", Toast.LENGTH_LONG).show()
                return true
            }
            item?.title == "Search" -> {
                Toast.makeText(applicationContext, "Search", Toast.LENGTH_LONG).show()
                return true
            }
            else -> return super.onContextItemSelected(item)
        }
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            R.id.add -> {
                Log.d("API123", "done")
                return true
            }
            R.id.call -> {
                Log.d("API123", "done")
                return true
            }
            R.id.day -> {
                Log.d("API123", "done")
                return true
            }
            R.id.compass -> {
                Log.d("API123", "done")
                return true
            }

            R.id.agenda -> {
                Log.d("API123", "done")
                return true
            }

            else -> return super.onOptionsItemSelected(item)
        }

    }
}

In the onCreateContextMenu: menu?.add(1, v?.id!!, 0, "Search") is used to add a new menu in the Context Menu.
The first param is the groupId. We can thus have different menu groups within a menu. The second is the menu item id. The third is the priority and the fourth is the title.

The output of the above application in action is given below:

androidly-menus-output

This brings an end to this tutorial. You can download the project from the link below:

Comments

  1. Eltayeb Mohamed says:

    Thanks. Good work. Very useful

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages