web-dev-qa-db-fra.com

Comment créer une instance de menu par programme? c'est-à-dire gonfler un menu en dehors de onCreateOptionsMenu

Je veux gonfler un objet de menu extérieuronCreateOptionsMenu méthode (ce qui signifie créer/afficher le menu lorsque l'utilisateur n'appuie pas sur le bouton), donc je dois créer une instance de menu pour le passer à la méthode de gonflage.

Voici un exemple de ce que j'essaie de réaliser:

Menu menu = // How to create an instance !? 
new MenuInflater(context).inflate(R.menu.my_menu, menu)

Le menu est une interface, j'ai donc besoin de savoir quelle classe l'implémente. J'ai parcouru Android code pour obtenir un indice sur la façon dont un objet Menu est créé, mais je n'ai toujours pas trouvé ce que je cherchais.

Modifier 1

Mon objectif est de déclencher un événement onOptionsItemSelected(MenuItem item) à partir d'une vue personnalisée, qui sera gérée par l'activité, j'ai donc besoin d'avoir un objet MenuItem avec un itemId et un titre spécifiques pour le passer avec l'événement.

Si je peux réussir à créer un objet Menu, il sera facile d'obtenir ses enfants MenuItems.

Modifier 2

Je pas essayant d'afficher un menu du tout, ce que je veux, c'est remplir un ListView avec des éléments défini dans un menu XML qui a un titre, une icône et un itemId et chaque fois qu'un ListViewItem est cliqué, je veux déclencher un événement onOptionsItemSelected(MenuItem item) qui est géré dans mon activité.

Je sais que je peux analyser le menu XML pour extraire des informations sur les éléments, mais je ne pourrai pas déclencher onOptionsItemSelected(MenuItem item) sans créer une norme Objet MenuItem pour le passer en argument.

Toute aide serait appréciée. Merci!

35
iTech

Voici une astuce pour obtenir une instance de Menu:

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

J'ai trouvé deux solutions pour créer par programmation une instance de menu et la gonfler:

// Création d'une instance par réflexion

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;
}

Une fois que vous avez une instance de Menu, vous pouvez facilement la gonfler à partir d'une ressource XML de menu n'importe où dans votre programme

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

J'ai testé les deux méthodes et elles fonctionnent parfaitement, je recommanderais d'utiliser la deuxième méthode avec les classes Menu et MenuItem standard de Android SDK même si votre activité étend SherlockActivity car elle recevra toujours onOptionsItemSelected(MenuItem item) que vous la déclenchiez avec Android.view.MenuItem ou com.actionbarsherlock.view.MenuItem

28
iTech

Vous n'avez rien à faire avec le gonfleur pour ajouter vos propres menus. Remplacez simplement onCreateOptionsMenu et commencez à ajouter vos propres éléments dans l'objet men. Par exemple:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    super.onCreateOptionsMenu(menu);

    menu.add(0, 1, Menu.NONE, "First");
    menu.add(0, 2, Menu.NONE, "Second");
    // repeat this to add additional menus

    return true;
}

Le deuxième argument de la méthode add est le id. Utilisez des identifiants uniques pour identifier l'élément de menu sélectionné.

2
waqaslam

Je ne sais pas pourquoi ce n'est pas déjà une réponse, et je sais que c'est une vieille question, mais pour les futurs lecteurs ..

Si vous faites simplement ceci:

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

Ça marche!

MenuBuilder étend éventuellement Android.view.Menu. Après inspection, c'est tout ce que PopupMenu fait.

Voici deux fonctions d'assistance et un exemple d'utilisation:

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:

Activité

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)

        ...
    }
}
2
Joshua King

Vous pouvez extraire une instance de MenuBuilder (qui implémente l'interface de menu) stockée dans PhoneWindow qui est utilisé dans Activity. J'ai une solution qui fonctionne, elle utilise Java Reflection.

J'ai créé un projet "InDroid" pour exposer quelques méthodes cachées importantes, des variables de Android platform- http://code.google.com/p/indroid/

BR, Prasanta

0
user542954