OnCreateOptionsMenu () no llamado en Fragmento

107

Tengo una aplicación que tiene una actividad con 2 fragmentos colocados horizontalmente.

En mi actividad, inflé el menú con el onCreateOptionsMenu()que puedo mostrar el menú de opciones de la barra de acción. Pero cuando intento actualizar los elementos del menú de la barra de acciones de uno de mis fragmentos, onCreateoptionsmenu()no se llama. Por lo tanto, no puedo actualizar el menú de opciones de la barra de acciones.

El código de mi actividad es el siguiente:

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
fuente

Respuestas:

296

En el onCreateView()método de su fragmento , debe llamar setHasOptionsMenu(true)para decirle a la actividad del host que su fragmento tiene opciones de menú que desea agregar.

dangVarmit
fuente
Hice el cambio, pero la aplicación se bloquea con 11-27 01: 55: 34.468: E / AndroidRuntime (12294): Causado por: java.lang.ClassCastException: com.android.internal.view.menu.MenuItemImpl no se puede transmitir a Android .widget.SearchView
Android_programmer_office
sí, encontré el problema. olvidé agregar getActionView () para searchView.
Android_programmer_office
2
También debe usar el tipo de vacío para onCreateOptionsMenu (menú de menú, inflador MenuInflater) el tipo booleano no funcionará
Bahaa Hany
15
Si está utilizando Toolbaren el diseño de su Actividad, asegúrese de llamar setSupportActionBar(your_toolbar)a su Actividad. De lo contrario, setHasOptionsMenuno tiene ningún efecto.
artkoenig
Eres mi hermano de amor :)
Qadir Hussain
30

Si está utilizando un tema que no es compatible con ActionBar, OnCreateOptionsMenu () no se llamará automáticamente, incluso si escribió todos los códigos Java correctamente.

Puede abrir AndroidManifest.xml, cambiar el valor de android: theme a "@android: style / Theme.Holo.Light.DarkActionBar", o cualquier otro tema que admita ActionBar.

animalizar
fuente
Estoy usando la barra de herramientas de la biblioteca de soporte y Theme.AppCompat.Light.NoActionBar como tema y estoy enfrentando el mismo problema ... no se muestra el menú de opciones..plz ayuda
Dhruvam Gupta
6
Lo resolví llamandotoolbar.inflateMenu(R.menu.menu_custom);
Dhruvam Gupta
Simplemente llame a setSupportActionBar (mToolbar) en su actividad y onCreateOptionsMenu en Fragments se llamará automáticamente.
Vít Kapitola
12

esto funcionó para mí

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

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

Además, asegúrese de que la instancia de la barra Google a la que está pasando

setSupportActionBar(toolbar);

en su Actividad no lo es null, porque no obtendrá una excepción si lo es nully perderá un par de horas como lo hice yo.

Solía butterknife para unir los puntos de vista, pero puse accidentalmente setSupportActionBar(toolbar)antes de que realmente hice la llamada aButterKnife.bind()

bulbo raquídeo de jack
fuente
1
Haris, eres increíble. ¡Gracias por compartir esto! Tuve este problema exacto porque estoy usando Kotlin y muchas veces no tienes que hacer findViewById, etc ... para obtener la vista que necesitas.
DWndrer
1

Simplemente dígale a la actividad del host que su fragmento tiene un menú de opciones en su constructor.

public YourFragment () {setHasOptionsMenu (verdadero);}

Aunque funcionó para mí, se desaconseja como se señaló en el comentario de @aldorain

Las aplicaciones generalmente no deben implementar un constructor. El primer lugar en el que se puede ejecutar el código de la aplicación donde el fragmento está listo para ser utilizado es onAttach (Actividad), el punto donde el fragmento está realmente asociado con su actividad.

Así que ponga setHasOptionsMenu (true) en onCreateView () o onAttach () en su lugar.

Ken Ratanachai S.
fuente
No debe escribir sus propios constructores para fragmentos personalizados
aldorain
1
developer.android.com/reference/android/app/Fragment.html tl; dr 'Por lo general, las aplicaciones no deberían implementar un constructor [Fragment].'
aldorain
0

Si tiene un tema que no le proporciona una AppBar por defecto y está utilizando una vista de barra de herramientas para proporcionar esta función, NO OLVIDE llamar a setSupportActionBar (barra de herramientas) en el método onCreate () de la actividad que aloja su fragmentos.

Después de eso, llame a setHasOptionsMenu (true) en su método de fragmento onCreate ().

:)

Moreno
fuente
-2

Establecer setHasOptionsMenu(true)en onCreateView()método en 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
fuente
1
Hola y bienvenido a SO. Por favor, no publique solo respuestas de código sin comentarios y mal formateadas, ya que esto no explica cuál fue exactamente el problema descrito en la pregunta. Consulte aquí algunos consejos generales sobre lo que constituye una buena respuesta.
Gero