web-dev-qa-db-fra.com

Android ajoutant un sous-menu à un menuItem, où se trouve addSubMenu ()?

Je souhaite ajouter un sous-menu dans mon OptionsMenu à un élément de menu, par programme, en fonction de mes paramètres. J'ai vérifié "MenuItem" dans Android SDK et il n'y a pas de méthode addSubMenu () !, bien que vous puissiez trouver "hasSubMenu ()" et "getSubMenu". 

Je pensais faire cela dans onCreateOptionsMenu:

public boolean onCreateOptionsMenu(Menu menu) {

    MenuItem mi = menu.getItem(MYITEMID);  // << this is defined in my XML optionsMenu
    SubMenu subm = mi.addSubMenu(0,1,0,"Map 1"); // no addSubMenu() method!!!???
....

Comment créer un sous-menu dans un menu sous code?

40
ruhalde

Parfois, l'étrangeté d'Android est vraiment incroyable (et amusante ..). Je l'ai résolu de cette façon:

a) Définissez en XML un espace réservé de sous-menu comme ceci:

<item Android:visible="true" Android:id="@+id/m_area"
   Android:titleCondensed="Areas"
   Android:title="Areas"
   Android:icon="@drawable/restaur"
   Android:enabled="true"> 
   <menu>
    <item Android:id="@+id/item1" Android:title="Placeholder"></item>
   </menu>
</item>

b) Obtenez un élément de sous-menu dans OnCreateOptionsMenu, effacez-le et ajoutez mes éléments de sous-menu, comme ceci:

    public boolean onCreateOptionsMenu(Menu menu) { 
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.mapoptions, menu);

            int idx=0;
            subm = menu.getItem(MYITEM_INDEX).getSubMenu(); // get my MenuItem with placeholder submenu
            subm.clear(); // delete place holder

            while(true)
            {
                anarea = m_areas.GetArea(idx); // get a new area, return null if no more areas
                if(anarea == null)
                    break;
                subm.add(0, SUBAREASID+idx, idx, anarea.GetName()); // id is idx+ my constant
                ++idx;
            }
}
63
ruhalde

Je sais que c’est une vieille question, mais j’ai juste rencontré ce problème moi-même… .. La façon la plus simple de le faire semble être de simplement spécifier l’élément lui-même en tant que sous-menu, puis d’ajouter à cet élément… ... Par exemple:

menu.add(groupId, MENU_VIEW, Menu.NONE, getText(R.string.menu_view));
menu.add(groupId, MENU_EDIT, Menu.NONE, getText(R.string.menu_edit));
SubMenu sub=menu.addSubMenu(groupId, MENU_SORT, Menu.NONE, getText(R.string.menu_sort));
sub.add(groupId, MENU_SORT_BY_NAME, Menu.NONE, getText(R.string.menu_sort_by_name));
sub.add(groupId, MENU_SORT_BY_ADDRESS, Menu.NONE, getText(R.string.menu_sort_by_address));
:
:
24
Einar H.

Voici une réponse complète qui repose sur l’idée d’utiliser un espace réservé, mais utilise principalement xml pour ajouter le sous-menu.

Si vous avez un menu comme celui appelé main_menu.xml:

<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:title="My Menu"
    Android:id="@+id/my_menu_item">
    <!-- A empty SubMenu -->
    <menu></menu>
</item>
</menu>

Créez un autre menu sub_menu.xml qui sera utilisé dans my_menu_item:

<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">
  <item Android:title="SubMenu One"
    Android:id="@+id/submenu_one" />
  <item Android:title="SubMenu Two"
    Android:id="@+id/submenu_two" />
  <item Android:title="SubMenu Three"
    Android:id="@+id/submenu_three" />
</menu>

Dans votre onCreateOptionsMenu:

public boolean onCreateOptionsMenu(Menu menu) {
   // Inflate your main_menu into the menu
   getMenuInflater().inflate(R.menu.main_menu, menu);

   // Find the menuItem to add your SubMenu
   MenuItem myMenuItem = menu.findItem(R.id.my_menu_item);

   // Inflating the sub_menu menu this way, will add its menu items 
   // to the empty SubMenu you created in the xml
   getMenuInflater().inflate(R.menu.sub_menu, myMenuItem.getSubMenu());

}

Cette solution est agréable car l’inflateur gère la majeure partie du travail.

18
Robert

La meilleure façon de le faire est dans votre fichier de menu XML. Vous pouvez le faire en créant un nouvel objet menu à l'intérieur d'une item:

<menu>
  <item>
    ...
    <menu>
      ...
    </menu>
    ...
  </item>
</menu>
13
Phil
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:id="@+id/menu1" Android:alphabeticShortcut="a"
    Android:title="Menu No. 1" Android:orderInCategory="1" />
<item Android:id="@+id/menu2" Android:alphabeticShortcut="b"
    Android:title="Menu No. 2" Android:orderInCategory="2">
    <menu >
    <group Android:id="@+id/group2" Android:checkableBehavior="single">
        <item Android:id="@+id/submenu1" Android:title="SubMenu No. 1" />
        <item Android:id="@+id/submenu2" Android:title="SubMenu No. 2" />
    </group>   
    </menu>
</item>

0

Je créerais simplement le sous-menu dans un fichier xml et, au moment de l'exécution, récupèrerais le sous-menu à partir de l'objet menu (en utilisant la méthode findItem (id)) et utiliser submenu.setVisible (booléen) pour l'ajouter/le supprimer au moment de l'exécution.

0
sorry_I_wont

Pour donner un exemple complet de la réponse de Phil, voici mon XML complet et fonctionnel pour un menu avec deux choix, chacun étant un menu avec trois choix. J'ai l'intention d'ajouter un troisième menu au niveau supérieur ...

<menu xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:HTMLCode="http://schemas.Android.com/apk/res-auto">

    <item Android:id="@+id/Examine"
        Android:title="@string/Examine"
        HTMLCode:showAsAction="always">

        <menu xmlns:Android="http://schemas.Android.com/apk/res/Android"
            xmlns:HTMLCode="http://schemas.Android.com/apk/res-auto" >
            <item Android:id="@+id/load"
                Android:title="@string/load"
                HTMLCode:showAsAction="ifRoom|withText" />

            <item Android:id="@+id/findfirst"
                Android:title="@string/findfirst"
                HTMLCode:showAsAction="ifRoom|withText" />

            <item Android:id="@+id/findnext"
                Android:title="@string/FindNext"
                HTMLCode:showAsAction="ifRoom|withText" />
        </menu>
    </item>

    <item Android:id="@+id/Redirect"
        Android:title="@string/Redirect"
        HTMLCode:showAsAction="ifRoom|withText">

        <menu xmlns:Android="http://schemas.Android.com/apk/res/Android"
            xmlns:HTMLCode="http://schemas.Android.com/apk/res-auto" >
            <item Android:id="@+id/getRedirect"
                Android:title="@string/getRedirect"
                HTMLCode:showAsAction="ifRoom|withText" />

            <item Android:id="@+id/toggleRedirect"
                Android:title="@string/toggleRedirect"
                HTMLCode:showAsAction="ifRoom|withText" />

            <item Android:id="@+id/copyRedirect"
                Android:title="@string/copyRedirect"
                HTMLCode:showAsAction="ifRoom|withText" />
        </menu>
    </item>
</menu>
0
Mick

Vous devriez plutôt utiliser un ActionProvider.

public class MyActionProvider extends ActionProvider {

    private Context mContext;

    public MyActionProvider(Context context) {
        super(context);

        mContext = context;
    }

    @Override
    public View onCreateActionView() {
        //LayoutInflater layoutInflater = LayoutInflater.from(mContext);
        return null;
    }

    @Override
    public void onPrepareSubMenu(SubMenu subMenu) {
        super.onPrepareSubMenu(subMenu);

        subMenu.clear();

        subMenu.add("menu 1");
        subMenu.add("menu 2");
        subMenu.add("menu 3");
    }

    @Override
    public boolean hasSubMenu() {
        return true;
    }

    @Override
    public boolean onPerformDefaultAction() {
        return super.onPerformDefaultAction();
    }
}
0
Sibelius Seraphini