OnCreateOptionsMenu () não chamado no Fragment

107

Eu tenho um aplicativo que tem uma atividade com 2 fragmentos colocados horizontalmente.

Na minha atividade, aumentei o menu com o onCreateOptionsMenu()qual sou capaz de exibir o menu de opções da barra de ações. Mas quando tento atualizar os itens de menu da barra de ação de um de meus fragmentos, o onCreateoptionsmenu()não é chamado. Portanto, não consigo atualizar o menu de opções da barra de ação.

O código em minha atividade é o seguinte:

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
fonte

Respostas:

296

No onCreateView()método de seu fragmento , você precisa chamar setHasOptionsMenu(true)para informar a atividade do host que seu fragmento tem opções de menu que deseja adicionar.

dangVarmit
fonte
Fiz a alteração, mas o aplicativo trava com 11-27 01: 55: 34.468: E / AndroidRuntime (12294): Causado por: java.lang.ClassCastException: com.android.internal.view.menu.MenuItemImpl não pode ser convertido para o Android .widget.SearchView
Android_programmer_office
sim eu encontrei o problema. esqueci de adicionar getActionView () para searchView.
Android_programmer_office
2
Além disso, você deve usar o tipo de vazio para onCreateOptionsMenu (menu Menu, MenuInflater inflater) o tipo booleano não funcionará
Bahaa Hany
15
Se você estiver usando Toolbarno layout de sua atividade, certifique-se de chamar setSupportActionBar(your_toolbar)sua atividade. Caso contrário setHasOptionsMenu, não tem efeito.
artkoenig
Você é meu amor, irmão :)
Qadir Hussain
30

Se você estiver usando um tema que não oferece suporte a ActionBar, OnCreateOptionsMenu () não será chamado automaticamente, mesmo que você tenha escrito todos os códigos Java corretamente.

Você pode abrir AndroidManifest.xml, alterar o valor de android: theme para "@android: style / Theme.Holo.Light.DarkActionBar" ou qualquer outro tema que suporte ActionBar.

animalizar
fonte
Estou usando a barra de ferramentas da biblioteca de suporte e Theme.AppCompat.Light.NoActionBar como tema e estou enfrentando o mesmo problema ... nenhum menu de opções exibido..plz help
Dhruvam Gupta
6
resolvi ligando paratoolbar.inflateMenu(R.menu.menu_custom);
Dhruvam Gupta
Basta chamar setSupportActionBar (mToolbar) em sua atividade e onCreateOptionsMenu em Fragments será chamado automaticamente.
Vít Kapitola
12

isso funcionou para mim

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

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

Além disso, certifique-se de que a instância da Barra de Ferramentas que você está passando

setSupportActionBar(toolbar);

em sua atividade não é null, porque você não terá uma exceção se for verdade nulle você perderá algumas horas como eu perdi.

Usei ButterKnife para vincular as visualizações, mas coloquei acidentalmente setSupportActionBar(toolbar)antes de realmente fazer a chamada paraButterKnife.bind()

medula oblongata de jack
fonte
1
Haris, você é incrível. Obrigado por compartilhar isso! Eu tive esse mesmo problema porque estou usando Kotlin e muitas vezes você não precisa fazer findViewById, etc ... para obter a visualização que você precisa.
DWndrer
1

Simplesmente diga à atividade do host que seu fragmento tem menu de opções em seu construtor.

public YourFragment () {setHasOptionsMenu (true);}

Embora tenha funcionado para mim, é desencorajado, conforme observado no comentário de @aldorain

Os aplicativos geralmente não devem implementar um construtor. O primeiro lugar em que o código do aplicativo pode ser executado onde o fragmento está pronto para ser usado é em onAttach (Activity), o ponto onde o fragmento está realmente associado à sua atividade.

Portanto, coloque setHasOptionsMenu (true) em onCreateView () ou onAttach ().

Ken Ratanachai S.
fonte
Você não deve escrever seus próprios construtores para fragmentos personalizados
aldorain
1
developer.android.com/reference/android/app/Fragment.html tl; dr 'Os aplicativos geralmente não devem implementar um construtor [Fragment].'
aldorain
0

Se você tem um tema que não fornece um AppBar por padrão e está usando uma visualização da barra de ferramentas para fornecer esse recurso, NÃO SE ESQUEÇA DE chamar setSupportActionBar (barra de ferramentas) no método onCreate () da atividade que hospeda seu fragmentos.

Depois disso, chame setHasOptionsMenu (true) em seu método de fragmento onCreate ().

:)

Moreno
fonte
-2

Definido setHasOptionsMenu(true)no onCreateView()método no fragmento.

@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
fonte
1
Olá e bem-vindo ao SO. Por favor, não publique apenas respostas não comentadas e mal formatadas, pois isso não explica exatamente qual era o problema descrito na pergunta. Verifique aqui algumas dicas gerais sobre o que constitui uma boa resposta.
Gero