OnCreateOptionsMenu () non appelé dans Fragment

107

J'ai une application qui a une activité avec 2 fragments placés horizontalement.

Dans mon activité, j'ai gonflé le menu à l' onCreateOptionsMenu()aide duquel je suis capable d'afficher le menu d'options de la barre d'action. Mais lorsque j'essaye de mettre à jour les éléments de menu de la barre d'actions à partir de l'un de mes fragments, le onCreateoptionsmenu()n'est pas appelé. Je ne suis donc pas en mesure de mettre à jour le menu d'options de la barre d'action.

Le code de mon activité est le suivant:

myActivity.java

package com.andr.androidtablelist;

import java.io.IOException;

import android.app.ActionBar;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;

import com.andr.fragments.ListLeftFragment;
import com.andr.utils.DBHelper;

      public class TabletActivity extends Activity {
    ActionBar actionBar = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DBHelper dbhelper;
        dbhelper = new DBHelper(this);
        try {
            dbhelper.createDatabase();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        setContentView(R.layout.activity_tablet);
        actionBar = getActionBar();
        actionBar.setDisplayHomeAsUpEnabled(false);
        getFragmentManager().beginTransaction()
                .replace(R.id.master, ListLeftFragment.newInstance()).commit();
    }

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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            Toast.makeText(
                    getApplicationContext(),
                    "Back Stack Count::"
                            + getFragmentManager().getBackStackEntryCount(),
                    Toast.LENGTH_LONG).show();
            if (getFragmentManager().getBackStackEntryCount() == 1) {
                actionBar.setDisplayHomeAsUpEnabled(false);
            }
            if (getFragmentManager().getBackStackEntryCount() > 1) {
                getFragmentManager().popBackStack();

            }
            return true;

        }
        return super.onOptionsItemSelected(item);
    }

}
      // http://www.vogella.com/articles/AndroidListView/article.html

myFragment.java

      package com.andr.fragments;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.TextView;

import com.andr.androidtablelist.R;
import com.andr.helper.LazyHelper;

   public class ListLeftFragment extends Fragment{
    private static ListLeftFragment listFragment = null;

    public static ListLeftFragment newInstance(){
        listFragment = new ListLeftFragment();      
        return listFragment;
    }

     @Override
    public void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);


    }

     @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
         View v =  inflater.inflate(R.layout.fragment_listlayout, container,false);
         getActivity().invalidateOptionsMenu();
         ListView lv = (ListView)v.findViewById(R.id.lview);
         String[] values = new String[] { "Android", "iPhone", "WindowsMobile",
                    "Blackberry", "WebOS", "Ubuntu", "Windows7", "Max OS X",
                    "Linux", "OS/2", "Ubuntu", "Windows7", "Max OS X", "Linux",
                    "OS/2", "Ubuntu", "Windows7", "Max OS X", "Linux", "OS/2",
                    "Android", "iPhone", "WindowsMobile" };
         getActivity().getActionBar().setTitle("LeftList");

          ArrayList<String> list = new ArrayList<String>();
         LazyHelper lHelper = new LazyHelper(getActivity());
         list = lHelper.getLazyDetials();

           /* for (int i = 0; i < values.length; ++i) {
              list.add(values[i]);
            }
            final StableArrayAdapter adapter = new StableArrayAdapter(getActivity(),
                android.R.layout.simple_list_item_1, list);*/
            LeftListAdapter lAdapter = new LeftListAdapter(getActivity(),list);
            lv.setAdapter(lAdapter);
            lv.setOnItemClickListener(new OnItemClickListener()
            {

                @Override
                public void onItemClick(AdapterView<?> arg0, View arg1,
                        int pos, long arg3) {
                    final String clickedData = (String)arg0.getItemAtPosition(pos);
                    Bundle bundle = new Bundle();
                    bundle.putString("clickedItemName", clickedData);
                    Fragment detailFragment = DetailFormRightFragment.newInstance();
                    detailFragment.setArguments(bundle);
                    getActivity().getFragmentManager().beginTransaction().replace(R.id.details, detailFragment).addToBackStack(null).commit();
                }

            }
                    );
         return v;
    }


     @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        getActivity().getMenuInflater().inflate(R.menu.search, menu);
        SearchView searchView=(SearchView)menu.findItem(R.id.search);
        searchView.setIconifiedByDefault(true);
    } 

     @Override
    public boolean onOptionsItemSelected(MenuItem item) {

         super.onOptionsItemSelected(item);
         return false;
    }


     @Override
    public void onPrepareOptionsMenu(Menu menu) {
         super.onPrepareOptionsMenu(menu);
        /*MenuItem item;
        menu.clear();
        getActivity().getMenuInflater().inflate(R.menu.search, menu);
        SearchView searchView=(SearchView)menu.findItem(R.id.search);
        searchView.setIconifiedByDefault(true);*/
    }

     private class StableArrayAdapter extends ArrayAdapter<String> {

            HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();

            public StableArrayAdapter(Context context, int textViewResourceId,
                List<String> objects) {
              super(context, textViewResourceId, objects);
              for (int i = 0; i < objects.size(); ++i) {
                mIdMap.put(objects.get(i), i);
              }
            }

            @Override
            public long getItemId(int position) {
              String item = getItem(position);
              return mIdMap.get(item);
            }

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

          }

     private class LeftListAdapter extends BaseAdapter implements OnClickListener {
         private Context mcontext;
         ArrayList<String> listData;
         private  LayoutInflater inflater=null;
         public LeftListAdapter(Context context, ArrayList<String> listItems) {
              mcontext=context;
              listData=listItems;
              inflater = (LayoutInflater)mcontext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         }

        @Override
        public int getCount() {
            return listData.size();
        }

        @Override
        public Object getItem(int arg0) {
            return null;
        }

        @Override
        public long getItemId(int arg0) {
            // TODO Auto-generated method stub
            return 0;
        }

        @Override
        public View getView(int position, View view, ViewGroup arg2) {
            // create a ViewHolder reference
            View vi=view;
            if(vi==null){
                vi = inflater.inflate(R.layout.item, null);
            }
            TextView text=(TextView)vi.findViewById(R.id.text);
            text.setText(listData.get(position));
            vi.setOnClickListener(this);
            return vi;
        }

        @Override
        public void onClick(View vi) {
            TextView text=(TextView)vi.findViewById(R.id.text);
            Bundle bundle = new Bundle();
            bundle.putString("clickedItemName", text.getText().toString());
            Fragment detailFragment = DetailFormRightFragment.newInstance();
            detailFragment.setArguments(bundle);
            getActivity().getFragmentManager().beginTransaction().replace(R.id.details, detailFragment).addToBackStack(null).commit();          
        }

     }
   }
Android_programmer_office
la source

Réponses:

296

Dans la onCreateView()méthode de votre fragment , vous devez appeler setHasOptionsMenu(true)pour indiquer à l'activité hôte que votre fragment a des options de menu à ajouter.

dangVarmit
la source
J'ai effectué le changement, mais l'application plante avec 11-27 01: 55: 34.468: E / AndroidRuntime (12294): Causé par: java.lang.ClassCastException: com.android.internal.view.menu.MenuItemImpl ne peut pas être casté sur Android .widget.SearchView
Android_programmer_office
ouais j'ai trouvé le problème. oublié d'ajouter getActionView () pour searchView.
Android_programmer_office
2
Vous devez également utiliser le type void pour onCreateOptionsMenu (menu menu, MenuInflater inflater) le type booléen ne fonctionnera pas
Bahaa Hany
15
Si vous utilisez Toolbardans la mise en page de votre activité, assurez-vous d'appeler setSupportActionBar(your_toolbar)votre activité. Sinon, cela setHasOptionsMenun'a aucun effet.
artkoenig
You are my love bro :)
Qadir Hussain
30

Si vous utilisez un thème qui ne pas charge ActionBar, OnCreateOptionsMenu () ne sera pas appelé automatiquement, même si vous avez écrit tous les codes Java correctement.

Vous pouvez ouvrir AndroidManifest.xml, changer la valeur de android: theme en "@android: style / Theme.Holo.Light.DarkActionBar" ou tout autre thème prenant en charge ActionBar.

animaliser
la source
J'utilise la barre d'outils de la bibliothèque de support et Theme.AppCompat.Light.NoActionBar comme thème et je suis confronté au même problème ... pas de menu d'options
affiché..plz
6
Je l'ai résolu en appelanttoolbar.inflateMenu(R.menu.menu_custom);
Dhruvam Gupta
Appelez simplement setSupportActionBar (mToolbar) dans votre activité et onCreateOptionsMenu dans Fragments sera appelé automatiquement.
Vít Kapitola le
12

cela a fonctionné pour moi

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    setHasOptionsMenu(true);
    View view = inflater.inflate(R.layout.sample, null);
}
Anisetti Nagendra
la source
11

Assurez-vous également que l'instance de la barre d'outils à laquelle vous passez

setSupportActionBar(toolbar);

dans votre activité ne l'est pas null, car vous n'obtiendrez pas d'exception si c'est le cas nullet vous perdrez quelques heures comme je l'ai fait.

J'ai utilisé ButterKnife pour lier les vues, mais setSupportActionBar(toolbar)je l'ai placé accidentellement avant d'appelerButterKnife.bind()

jack's medulla oblongata
la source
1
Haris, tu es génial. Merci d'avoir partagé ça! J'ai eu ce problème exact parce que j'utilise Kotlin et souvent vous n'avez pas à faire findViewById, etc ... pour obtenir la vue dont vous avez besoin.
DWndrer
1

Dites simplement à l'activité hôte que votre fragment a un menu d'options dans son constructeur.

public YourFragment () {setHasOptionsMenu (true);}

Bien que cela ait fonctionné pour moi, c'est déconseillé comme indiqué dans le commentaire de @aldorain

Les applications ne doivent généralement pas implémenter un constructeur. Le premier endroit où le code d'application peut s'exécuter là où le fragment est prêt à être utilisé est onAttach (Activity), le point où le fragment est réellement associé à son activité.

Mettez donc setHasOptionsMenu (true) dans onCreateView () ou onAttach () à la place.

Ken Ratanachai S.
la source
Vous ne devriez pas écrire vos propres constructeurs pour les fragments personnalisés
aldorain
1
developer.android.com/reference/android/app/Fragment.html tl; dr "Les applications ne doivent généralement pas implémenter un constructeur [Fragment]."
aldorain
0

Si vous avez un thème qui ne vous fournit pas d'AppBar par défaut et que vous utilisez une vue de barre d'outils pour fournir cette fonctionnalité à la place, N'OUBLIEZ PAS d'appeler setSupportActionBar (barre d'outils) dans la méthode onCreate () de l'activité qui héberge votre fragments.

Après cela, appelez setHasOptionsMenu (true) dans votre méthode fragment onCreate ().

:)

Moreno
la source
-2

Mettre setHasOptionsMenu(true)en onCreateView()méthode dans le fragment.

@Override

 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) 
 {
    Viewroot=inflater.inflate(R.layout.fragment_client_requestfragment,container,false);
  hideKeyboard();
    getemail = getArguments().getString("email_id");
    Log.e("email_id from activity",getemail);
    setHasOptionsMenu(true);
    return root;
}
Nimisha Patel
la source
1
Bonjour et bienvenue à SO. Veuillez ne pas simplement publier des réponses non commentées et mal formatées en code uniquement, car cela n'explique pas exactement quel était le problème décrit dans la question. Consultez ici quelques conseils généraux sur ce qui constitue une bonne réponse.
Gero