Search code examples
androidpopupmenunavigationview

Anchoring a PopupMenu to Navigationview menu items


Since this question and its answer didn't show up anywhere, thought I might as well contribute a little for once by sharing the way I found.

So I had this issue with anchoring a PopupMenu object to a NavigationView menu since I couldn't get any items out of it in the form of a view:

//onCreate:
     NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
        drawerMenu = navigationView.getMenu();


//onNavigationItemSelected(MenuItem menuItem):
     switch (menuItem.getItemId()) {
                case R.id.menubutton_submenuButton:
                    //the following line is merely how I'd imagine it should be
                    PopupMenu popupMenu = new PopupMenu(this, drawerMenu.findItem(R.id.menubutton_submenuButton));
                    popupMenu.getMenuInflater().inflate(R.menu.sub_menu, popupMenu.getMenu());
                    popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                        @Override
                        public boolean onMenuItemClick(MenuItem item) {
                            //handle the inflated menu's buttons here
                            return true;
                        }
                    });
                    popupMenu.show();
                    break;
    }

So then, the problem is basically where

drawerMenu.findItem(R.id.menubutton_submenuButton));

isn't a View of any sort, which leaves the PopupMenu with nothing to anchor to.


Solution

  • So I figured you can just create an empty view inside the menu item as follows: create a layout xml file including only the following:

    <?xml version="1.0" encoding="utf-8"?>
    <View
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        />
    

    lets call it "view_empty".

    Now the menu item should have that empty view layout included inside of it by adding the following line to its item: app:actionLayout="@layout/drawer_empty"
    My item looks as follows:

    <item
                    android:id="@+id/menubutton_submenuButton"
                    android:title="example menu item"
                    app:actionLayout="@layout/view_empty"/>
    

    Now then, all that's left is just using it:

    //onNavigationItemSelected(MenuItem menuItem) {
            switch (menuItem.getItemId()) {
                case R.id.menubutton_submenuButton:
                    MenuItem item = drawerMenu.findItem(R.id.menubutton_submenuButton);
                    PopupMenu popupMenu = new PopupMenu(this, MenuItemCompat.getActionView(item));
                    popupMenu.getMenuInflater().inflate(R.menu.sub_menu, popupMenu.getMenu());
                    popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                        @Override
                        public boolean onMenuItemClick(MenuItem item) {
                            //handle the inflated menu's buttons here
                            return true;
                        }
                    });
                    popupMenu.show();
                    break;
    

    What'd happen now is that the PopupMenu would anchor itself to an invisible view inside the menuItem, thus making it look like the container menuItem is the anchor point.