web-dev-qa-db-fra.com

Android Menu Options dans Fragment

J'essaie d'ajouter un élément au menu d'options à partir d'un groupe de fragments.

J'ai créé une nouvelle classe MenuFragment et l'ai étendue pour les fragments dans lesquels je souhaite inclure l'élément de menu. Voici le code:

public class MenuFragment extends Fragment {

    MenuItem fav;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        fav = menu.add("add");
        fav.setIcon(R.drawable.btn_star_big_off);
    }
}

Pour une raison quelconque, la onCreateOptionsMenu ne semble pas fonctionner.

372
misterbassman

Appelez la super méthode:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // TODO Add your menu entries here
    super.onCreateOptionsMenu(menu, inflater);
}

Mettez des instructions de journal dans le code pour voir si la méthode n'est pas appelée ou si le menu n'est pas modifié par votre code.

Assurez-vous également que vous appelez setHasOptionsMenu(boolean) dans onCreate(Bundle) pour indiquer au fragment qu'il doit participer à la gestion du menu d'options.

572
Kuffs

J'ai eu le même problème, mais je pense qu'il est préférable de résumer et d'introduire la dernière étape pour le faire fonctionner:

  1. Ajoutez la méthode setHasOptionsMenu (true) dans la méthode onCreate(Bundle savedInstanceState) de votre fragment.

  2. Remplacez onCreateOptionsMenu(Menu menu, MenuInflater inflater) (si vous voulez faire quelque chose de différent dans le menu de votre Fragment) et onOptionsItemSelected(MenuItem item) méthodes dans votre Fragment.

  3. Dans la méthode de votre onOptionsItemSelected(MenuItem item) Activity, assurez-vous de renvoyer false lorsque l'action de l'élément de menu serait implémentée dans la méthode de onOptionsItemSelected(MenuItem item) Fragment.

Un exemple:

Activité

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getSupportMenuInflater();
    inflater.inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.activity_menu_item:

            // Do Activity menu item stuff here
            return true;

        case R.id.fragment_menu_item:

            // Not implemented here
            return false;
        default:
            break;
    }

    return false;
}

Fragment

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
    ....
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // Do something that differs the Activity's menu here
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.activity_menu_item:

            // Not implemented here
            return false;
        case R.id.fragment_menu_item:

            // Do Fragment menu item stuff here
            return true;

        default:
            break;
    }

    return false;
}
188
Marco HC

Si vous trouvez que la méthode onCreateOptionsMenu(Menu menu, MenuInflater inflater) n'est pas appelée, assurez-vous d'appeler ce qui suit à partir de la méthode onCreate(Bundle savedInstanceState) du fragment:

setHasOptionsMenu(true)
154

Si vous avez besoin d'un menu pour actualiser un webview à l'intérieur d'un Fragment spécifique, vous pouvez utiliser:

fragment:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

    // TODO Add your menu entries here
    inflater.inflate(R.menu.menu, menu);
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.exit:
        System.exit(1);
        break;

    case R.id.refresh:
        webView.reload();
        break;
    }
    return true;

}

menu.xml

<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item Android:id="@+id/exit" Android:title="Exit" Android:icon="@drawable/ic_action_cancel" />
    <item Android:id="@+id/refresh" Android:title="Refresh" Android:icon="@drawable/ic_action_refresh" />
</menu>
51
Pedro Lobito

Dans le menu.xml, vous devez ajouter tous les éléments de menu. Vous pouvez ensuite masquer les éléments que vous ne souhaitez pas voir lors du chargement initial.

menu.xml

<item
    Android:id="@+id/action_newItem"
    Android:icon="@drawable/action_newItem"
    Android:showAsAction="never"
    Android:visible="false"
    Android:title="@string/action_newItem"/>

Ajoutez setHasOptionsMenu(true) dans la méthode onCreate () pour appeler les éléments de menu de votre classe Fragment.

FragmentClass.Java

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

Vous n'avez pas besoin de redéfinir onCreateOptionsMenu dans votre classe Fragment. Les éléments de menu peuvent être modifiés (Ajouter/Supprimer) en remplaçant la méthode onPrepareOptionsMenu disponible dans Fragment.

@Override
public void onPrepareOptionsMenu(Menu menu) {
    menu.findItem(R.id.action_newItem).setVisible(true);
    super.onPrepareOptionsMenu(menu);

}
23

Vous devez utiliser menu.clear () avant de gonfler les menus.

@Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        menu.clear();
        inflater.inflate(R.menu.menu, menu);
        super.onCreateOptionsMenu(menu, inflater);
    }

et

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }
16
Spl2nky

TL; DR

Utilisez le Android.support.v7.widget.Toolbar et faites simplement:

toolbar.inflateMenu(R.menu.my_menu)
toolbar.setOnMenuItemClickListener {
    onOptionsItemSelected(it)
}

Barre d'outils autonome

La plupart des solutions suggérées telles que setHasOptionsMenu(true) ne fonctionnent que lorsque l'activité parent a la barre d'outils dans sa présentation et la déclare via setSupportActionBar(). Ensuite, les fragments peuvent participer au menu population de cette ActionBar exacte :

Fragment.onCreateOptionsMenu (): initialise le contenu du menu d'options standard du Fragment Host.

Si vous voulez une barre d’outils autonome et un menu pour un fragment spécifique vous pouvez faire ce qui suit:

menu_custom_fragment.xml

<menu xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto">
    <item
        Android:id="@+id/menu_save"
        Android:title="SAVE" />
</menu>

custom_fragment.xml

<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <Android.support.v7.widget.Toolbar
        Android:id="@+id/toolbar"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content" />

    ...

CustomFragment.kt

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    val view = inflater.inflate(layout.custom_fragment, container, false)
    val toolbar = view.findViewById<Toolbar>(R.id.toolbar)
    toolbar.inflateMenu(R.menu.menu_custom_fragment)
    toolbar.setOnMenuItemClickListener {
        onOptionsItemSelected(it)
    }
    return view
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    return when (item.itemId) {
        R.id.menu_save -> {
            // TODO: User clicked the save button
            true
        }
        else -> super.onOptionsItemSelected(item)
    }
}

Oui, c'est aussi simple que ça. Vous n'avez même pas besoin de remplacer onCreate() ou onCreateOptionsMenu().

PS: Ceci ne fonctionne qu'avec Android.support.v4.app.Fragment et Android.support.v7.widget.Toolbar (veillez également à utiliser AppCompatActivity et un thème AppCompat dans votre styles.xml).

14
Marius

Dans mon cas, voici les étapes.

Étape 1

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Here notify the fragment that it should participate in options menu handling.
    setHasOptionsMenu(true);
}

Étape 2

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // First clear current all the menu items
    menu.clear();

    // Add the new menu items
    inflater.inflate(R.menu.post_stuff, menu);

    super.onCreateOptionsMenu(menu, inflater);
}

Étape 3

 @Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.post_stuff:
            Log.d(TAG, "Will post the photo to server");
            return true;
        case R.id.cancel_post:
            Log.d(TAG, "Will cancel post the photo");
            return true;
        default:
            break;
    }
    return super.onOptionsItemSelected(item);
}
9
Harry Zhang

Si vous voulez ajouter votre menu personnalisé

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.menu_custom, menu);
}
7
Ezequiel García

J'ai eu le même problème, mes fragments étaient des pages d'un ViewPager. La raison en était que j'utilisais le gestionnaire de fragments enfant plutôt que le gestionnaire de fragments de support d'activité lors de l'instanciation de FragmentPagerAdapter.

7
farid_z

Votre code est bon. Il ne manquait que le super dans la méthode:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // TODO add your menu : 
    inflater.inflate(R.menu.my_menu, menu);
    //TODO call super
    super.onCreateOptionsMenu(menu, inflater);
}
3
AlexPad

Fichier de menu:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item
        Android:id="@+id/play"
        Android:titleCondensed="Speak"
        Android:showAsAction="always"
        Android:title="Speak"
        Android:icon="@drawable/ic_play">
    </item>
    <item
        Android:id="@+id/pause"
        Android:titleCondensed="Stop"
        Android:title="Stop"
        Android:showAsAction="always"
        Android:icon="@drawable/ic_pause">
    </item>
</menu>

Code d'activité:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.speak_menu_history, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.play:
            Toast.makeText(getApplicationContext(), "speaking....", Toast.LENGTH_LONG).show();
            return false;

        case R.id.pause:
            Toast.makeText(getApplicationContext(), "stopping....", Toast.LENGTH_LONG).show();
            return false;

        default:
            break;
    }

    return false;
}

Code de fragment:

@Override

public void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        case R.id.play:
            text = page.getText().toString();
            speakOut(text);

            // Do Activity menu item stuff here
            return true;

        case R.id.pause:
            speakOf();

            // Not implemented here
            return true;

        default:
            break;
    }
    return false;
}
3
Suyog Gunjal

Je devenais fou parce qu'aucune des réponses ici ne fonctionnait pour moi.

Pour afficher le menu, j'ai dû appeler:setSupportActionBar(toolbar)

Terminé!

Remarque: si votre vue toolbar ne se trouve pas dans la même structure d'activité, vous ne pouvez pas utiliser l'appel ci-dessus directement à partir de votre classe d'activité. Dans ce cas, vous devez extraire cette activité de votre classe de fragment, puis appeler la setSupportActionBar(toolbar). Rappel: votre classe d'activité devrait étendre AppCompatActivity.

J'espère que cette réponse vous aidera.

2
Filipe Brito

La définition du menu des options après la création de la vue fragmentée a bien fonctionné pour moi.

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    setHasOptionsMenu(true);        
}
1
Jerry Frost

Dans votre dossier de menu, créez un fichier .menu xml et ajoutez-le. Xml

<item
    Android:id="@+id/action_search"
    Android:icon="@Android:drawable/ic_menu_search"
    Android:title="@string/action_search"
    app:actionViewClass="Android.support.v7.widget.SearchView"
    app:showAsAction="always|collapseActionView" />

Dans votre classe de fragment, passez outre cette méthode et

implement SearchView.OnQueryTextListener    in your fragment class



@Override
 public void onViewCreated(View view, Bundle savedInstanceState) {    
  super.onViewCreated(view, savedInstanceState);
  setHasOptionsMenu(true);

}

Maintenant, configurez votre fichier xml de menu dans la classe fragment

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.menu_main, menu);

    final MenuItem item = menu.findItem(R.id.action_search);
    final SearchView searchView = (SearchView)    
    MenuItemCompat.getActionView(item);


    MenuItemCompat.setOnActionExpandListener(item,
            new MenuItemCompat.OnActionExpandListener() {
                @Override
                public boolean onMenuItemActionCollapse(MenuItem item) {
                    // Do something when collapsed

                    return true; // Return true to collapse action view
                }

                @Override
                public boolean onMenuItemActionExpand(MenuItem item) {
                    // Do something when expanded
                    return true; // Return true to expand action view
                }
            });

}
1
pavel

Mon problème était légèrement différent. J'ai tout fait correctement. Mais j'héritais de la mauvaise classe pour l'activité hébergeant le fragment.

En clair, si vous écrasez onCreateOptionsMenu(Menu menu, MenuInflater inflater) dans le fragment, assurez-vous que votre classe d'activité hébergeant ce fragment hérite de Android.support.v7.app.ActionBarActivity (au cas où vous souhaiteriez prendre en charge un niveau inférieur à l'API 11).

J'héritais du Android.support.v4.app.FragmentActivity pour prendre en charge un niveau d'API inférieur à 11.

1
Krishna Deepak

Une chose que je voudrais ajouter à cela et la raison pour laquelle cela ne fonctionnait pas pour moi.

Cela ressemble à la réponse de Napster.

  1. Assurez-vous que l'activité d'hébergement de votre fragment s'étend AppCompatActivity et non FragmentActivity!

    public class MainActivity extends AppCompatActivity {
    
    }
    

    De la référence Google Documentation pour FragmentActivity:

    Remarque: Si vous souhaitez implémenter une activité comprenant une barre d'actions, vous devez plutôt utiliser la classe ActionBarActivity, qui est une sous-classe de celle-ci, vous permettant ainsi d'utiliser les API de fragmentation à partir du niveau 7.

  2. Pour mettre à jour la réponse de Napster - ActionBarActivity maintenant obsolète, utilisez plutôt AppCompatActivity.

  3. Lorsque vous utilisez AppCompatActivity, veillez également à définir "le thème de l'activité toTheme.AppCompat ou un thème similaire" (Google Doc).

Remarque: Android.support.v7.app.AppCompatActivity est une sous-classe de la classe Android.support.v4.app.FragmentActivity (voir AppCompatActivity ref doc).

1
bastien

Si tout ce qui précède ne fonctionne pas, vous devez déboguer et vous assurer que la fonction onCreateOptionsMenu a été appelée (en plaçant le journal de débogage ou d'écriture ...)

S'il n'est pas exécuté, votre thème Android ne prend peut-être pas en charge la barre d'action. Ouvrez AndroidManifest.xml et définissez la valeur pour Android:theme avec la barre d'action de prise en charge de thème:

 <activity
     Android:name=".MainActivity"
     Android:label="@string/app_name"
     Android:theme="@style/Theme.AppCompat">
0
Grey Wolf

sur votre méthode onCreate, ajoutez setHasOptionMenu ()

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

Alors annulation votre onCreateOptionsMen

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    menu.add("Menu item")
            .setIcon(Android.R.drawable.ic_delete)
            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
0
Ashana.Jackol