Android Tip: Detecting overflow button click event in Options Menu

    In Android, the options menu is where you should include actions and other options that are relevant to the current activity context, such as "Search," "Compose email," and "Settings". The option menu always located in Action Bar/Toolbar (from API 11):
    In this post, I would like to talk about overflow button in the option menu (number (3) in the picture). By setting app:showAsAction="never" with an <item>, it will be hidden in the overflow button.
    Handling click event of each menu item is a basic work in Android app development and this is not hard to do, you only need to override onOptionsItemSelected(Menu menu) method and based on their id to perform different tasks. But, are we be able to handling the overflow button click event?
    The answer is "Yes", when click the overflow button, a menu will be shown and onMenuOpened() was called. This method description can be seen at the official document of Google developer:
boolean onMenuOpened (int featureId, Menu menu): Called when a panel's menu is opened by the user. This may also be called when the menu is changing from one type to another (for example, from the icon menu to the expanded menu).
    Absolutely similarly, onPanelClosed() will be called when the option menu closed. According to Google doc, we can notice this:
void onPanelClosed (int featureId, Menu menu): Default implementation of onPanelClosed(int, Menu) for activities. This calls through to onOptionsMenuClosed(Menu) method for the FEATURE_OPTIONS_PANEL panel, so that subclasses of Activity don't need to deal with feature codes. For context menus (FEATURE_CONTEXT_MENU), the onContextMenuClosed(Menu) will be called.
    For example, suppose we have a menu file like this:
res/menu_main.xml
<?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/add"
        android:icon="@android:drawable/ic_menu_add"
        android:title="add"
        app:showAsAction="always" />

    <!-- Hidden in overflow button -->
    <item
        android:id="@+id/btn1"
        android:icon="@android:drawable/ic_menu_add"
        android:title="Item 1"
        app:showAsAction="never" />

    <item
        android:id="@+id/btn2"
        android:icon="@android:drawable/ic_menu_add"
        android:title="Item 2"
        app:showAsAction="never" />

    <item
        android:id="@+id/btn3"
        android:icon="@android:drawable/ic_menu_add"
        android:title="Item 3"
        app:showAsAction="never" />
</menu>
    And in the main activity, putting this code:
MainActivity.java
package info.devexchanges.overflowbuttonevent;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onMenuOpened(int featureId, Menu menu) {

        Log.i("MainActivity", "open");
        return super.onMenuOpened(featureId, menu);
    }

    @Override
    public void onPanelClosed(int featureId, Menu menu) {
        super.onPanelClosed(featureId, menu);
        Log.i("MainActivity", "closed");
    }
}
    After running this activity and open/close the menu in overflow button, we have this output in LogCat:
1686-1686/info.devexchanges.overflowbuttonevent I/MainActivity: open
1686-1686/info.devexchanges.overflowbuttonevent I/MainActivity: open
1686-1686/info.devexchanges.overflowbuttonevent I/MainActivity: closed
1686-1686/info.devexchanges.overflowbuttonevent I/MainActivity: closed
1686-1686/info.devexchanges.overflowbuttonevent I/MainActivity: closed
1686-1686/info.devexchanges.overflowbuttonevent I/MainActivity: closed
    As you can see, onMenuOpened() and onPanelClosed() were called many times with only one open/close action. If you would like to do something when the menu opened/closed, please attention, just do it at the first time 2 methods called!
    For example, showing a Toast when clicking at this overflow button, just rewrite your activity code like this:
MainActivity.java
package info.devexchanges.overflowbuttonevent;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private boolean isOpened = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.add) {
            Toast.makeText(this, "Adding button in action bar clicked", Toast.LENGTH_SHORT).show();
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onMenuOpened(int featureId, Menu menu) {
        if (!isOpened) Toast.makeText(this, "Menu opened", Toast.LENGTH_SHORT).show();
        isOpened = true;
        return super.onMenuOpened(featureId, menu);
    }

    @Override
    public void onPanelClosed(int featureId, Menu menu) {
        super.onPanelClosed(featureId, menu);
        if (isOpened) Toast.makeText(this, "menu closed", Toast.LENGTH_SHORT).show();
        isOpened = false;
    }
}
    Running this code, you'll notice that the Toast show only one time when menu opened/closed:
    References:

Share


Previous post
« Prev Post
Next post
Next Post »