How to create a Menu instance programmatically? i.e. inflate a Menu outside onCreateOptionsMenu

Here's a trick to get an instance of Menu:

PopupMenu p  = new PopupMenu(getContext(), null);
Menu menu = p.getMenu();

I found two solutions to programmatically create a Menu instance and inflate it:

  • Using ActionbarSherlock library or AppCompat v7 library Menu menu = new MenuBuilder(context); or you can write your own MenuBuilder class

  • Using standard android SDK:

// Creating an instance by reflection

Menu menu = newMenuInstance(context);


protected Menu newMenuInstance(Context context) {
    try {
        Class<?> menuBuilderClass = Class.forName("com.android.internal.view.menu.MenuBuilder");

        Constructor<?> constructor = menuBuilderClass.getDeclaredConstructor(Context.class);

        return (Menu) constructor.newInstance(context);

    } catch (Exception e) {e.printStackTrace();}

    return null;
}

Once you have a Menu instance you can easily inflate it from a menu XML resource anywhere in your program

new MenuInflater(context).inflate(menuId, menu);

I tested both methods and they are working perfectly, I would recommend using the second method with the standard Menu and MenuItem classes from android SDK even if your activity extends SherlockActivity because it will still receive onOptionsItemSelected(MenuItem item) regardless if you fire it with android.view.MenuItem or com.actionbarsherlock.view.MenuItem


I'm not sure why this isn't an answer already, and I know this is an old question, but for future readers..

If you simply do this:

val menu = MenuBuilder(context)
MenuInflater(context).inflate(R.menu.menu_XXXX, menu)

It works!

androidx.appcompat.view.menu.MenuBuilder implements android.view.Menu. Upon inspection, that's all that PopupMenu does.

Note that the com.android.internal.view.menu.MenuBuilder mentioned by @iTech and used by PopupMenu is not public and should not be used.

Here are two helper functions and a usage example:

fun Context.inflateMenu(@MenuRes menuRes: Int): Lazy<MenuBuilder> = lazy {
    MenuBuilder(this)
        .also { MenuInflater(this).inflate(menuRes, it) }
}

fun Fragment.inflateMenu(@MenuRes menuRes: Int): Lazy<MenuBuilder> = lazy {
    MenuBuilder(context)
        .also { MenuInflater(context).inflate(menuRes, it) }
}

Usage:

Activity

class MyActivity : AppCompatActivity(R.layout.activity_my) {

    val menu by inflateMenu(R.menu.menu_my)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        ...
    }
}

Fragment:

class MyFragment : Fragment(R.layout.fragment_my) {

    val menu by inflateMenu(R.menu.menu_my)

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        ...
    }
}