Menú de opciones de Android en Fragmento

Estoy tratando de agregar un elemento al menú de opciones de un grupo de fragmentos.

He creado una nueva clase MenuFragment y extendí esto para los fragmentos en los que deseo incluir el elemento del menú. Aquí está el código:

 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); } } 

Por alguna razón, el onCreateOptionsMenu parece no ejecutarse.

Llamar al súper método:

 @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); } 

Coloque declaraciones de registro en el código para ver si no se está llamando al método o si su código no está modificando el menú.

También asegúrese de estar llamando a SetHasOptionsMenu en onCreate para notificar al fragmento que debe participar en el manejo del menú de opciones.

Tuve el mismo problema, pero creo que es mejor resumir e introducir el último paso para que funcione:

  1. Agregue el método setHasOptionsMenu (verdadero) en el método onCreate(Bundle savedInstanceState) su Fragmento.

  2. onCreateOptionsMenu(Menu menu, MenuInflater inflater) (si desea hacer algo diferente en el menú de su Fragmento) y onOptionsItemSelected(MenuItem item) en su Fragmento.

  3. Dentro del método de la actividad onOptionsItemSelected(MenuItem item) , asegúrese de devolver false cuando la acción del elemento de menú se implemente en el onOptionsItemSelected(MenuItem item) Fragment.

Un ejemplo:

Actividad

 @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; } 

Fragmento

 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; } 

Si encuentra que no se invoca el método onCreateOptionsMenu(Menu menu, MenuInflater inflater) , asegúrese de llamar al siguiente método del Fragment onCreate(Bundle savedInstanceState) :

 setHasOptionsMenu(true) 

En mi caso, necesitaba un menú para actualizar una vista webview dentro de un Fragmento específico, para eso utilicé:

Fragmento :

 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; } 

Archivo menu.xml

     

En menu.xml , debe agregar todos los elementos del menú. Luego puede ocultar los elementos que no desea ver en la carga inicial.

menu.xml

  

Agregue setHasOptionsMenu(true) en el método onCreate () para invocar los elementos del menú en su clase Fragment.

FragmentClass.java

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

No necesita reemplazar onCreateOptionsMenu en su clase Fragment nuevamente. Los elementos del menú se pueden cambiar (Agregar / eliminar) anulando el método onPrepareOptionsMenu disponible en Fragment.

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

Necesita usar menu.clear () antes de inflar los menús.

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

y

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

Tuve el mismo problema, mis fragmentos eran páginas de un ViewPager. La razón por la que sucedió es que estaba usando el administrador de fragmentos hijo en lugar del administrador de fragmentos de soporte de actividades al crear instancias de FragmentPagerAdapter.

En mi caso, aquí están los pasos.

Paso 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); } 

Paso 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); } 

Paso 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); } 

Si quieres agregar tu menú personalizado

 @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); } 

Archivo de menú:

 < ?xml version="1.0" encoding="utf-8"?>       

Código de actividad:

 @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; } 

Código de fragmento:

 @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; } 

Tu código está bien. Solo el súper faltaba en el método:

 @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); } 

Me estaba volviendo loco porque ninguna de las respuestas aquí funcionó para mí.

Para mostrar el menú que tuve que llamar: setSupportActionBar(toolbar)

¡Hecho!

Nota: si la vista de la toolbar no está en el mismo diseño de actividad, no puede usar la llamada anterior directamente desde su clase de actividad, en este caso deberá obtener esa actividad de su clase de fragmento y luego llamar a la setSupportActionBar(toolbar) Recordando: su clase de actividad debe extender AppCompatActivity.

Espero que esta respuesta te ayude.

TL; DR

Utilice android.support.v7.widget.Toolbar y simplemente haga lo siguiente:

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

Barra de herramientas independiente

La mayoría de las soluciones sugeridas, como setHasOptionsMenu(true) , solo funcionan cuando la actividad primaria tiene la barra de herramientas en su diseño y la declara a través de setSupportActionBar() . Entonces los Fragmentos pueden participar en la población del menú de esta Barra de Acción exacta:

Fragment.onCreateOptionsMenu (): Inicializa el contenido del menú de opciones estándar del host Fragment.

Si desea una barra de herramientas independiente y un menú para un Fragmento específico , puede hacer lo siguiente:

menu_custom_fragment.xml

    

custom_fragment.xml

   ... 

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(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) } } 

Sí, es así de fácil. Ni siquiera necesita sobrescribir onCreate() o onCreateOptionsMenu() .

PD: Esto solo funciona con android.support.v4.app.Fragment y android.support.v7.widget.Toolbar (también asegúrese de usar AppCompatActivity y un tema de AppCompat en su styles.xml ).

Establecer el menú de opciones después de crear la vista de fragmento funcionó bien para mí.

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

Mi problema fue un poco diferente. Hice todo bien. Pero estaba heredando la clase incorrecta para la actividad que aloja el fragmento.

Entonces, para ser claros, si está anulando onCreateOptionsMenu(Menu menu, MenuInflater inflater) en el fragmento, asegúrese de que su clase de actividad que aloja este fragmento herede android.support.v7.app.ActionBarActivity (en caso de que desee admitir debajo de API nivel 11).

Estaba heredando la android.support.v4.app.FragmentActivity para admitir el nivel de API por debajo de 11.

Una cosa que agregaría a esto y la razón por la que no estaba funcionando para mí.

Es similar a la respuesta de Napster.

  1. ¡Asegúrese de que la actividad de alojamiento de su fragmento extienda AppCompatActivity , no FragmentActivity !

     public class MainActivity extends AppCompatActivity { } 

    De la documentación de referencia de Google para FragmentActivity:

    Nota: Si desea implementar una actividad que incluya una barra de acciones, en su lugar debe usar la clase ActionBarActivity, que es una subclase de esta, por lo que le permite usar las API de Fragment en API nivel 7 y superior.

  2. Para actualizar la respuesta de Napster – ActionBarActivity ahora está en desuso, use AppCompatActivity en AppCompatActivity lugar.

  3. Al usar AppCompatActivity , también asegúrese de establecer “el tema de actividad en Theme.AppCompat o un tema similar” (Google Doc).

Nota: android.support.v7.app.AppCompatActivity es una subclase de la clase android.support.v4.app.FragmentActivity (ver AppCompatActivity ref doc).

En su carpeta de menú, haga un archivo .menu xml y agregue este xml

  

En su clase de fragmento sobre este método y

 implement SearchView.OnQueryTextListener in your fragment class @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); setHasOptionsMenu(true); } 

Ahora solo configura tu archivo de menú xml en la clase de fragmento

 @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 } }); } 

Si todo lo anterior no funciona, debe depurar y asegurarse de que se haya llamado a la función onCreateOptionsMenu (colocando el registro de depuración o escritura …)

Si no se ejecuta, tal vez su tema de Android no sea compatible con la barra de acciones. Abra AndroidManifest.xml y establezca el valor de android:theme con la barra de acciones de soporte de tema :

   

en su método onCreate , agregue setHasOptionMenu ()

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

A continuación, anule su onCreateOptionsMenu

 @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); }