studio - Menú de opciones de Android en fragmento
llamar un fragment desde un activity (19)
TL; DR
Use android.support.v7.widget.Toolbar
y simplemente haga:
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 principal tiene la barra de herramientas en su diseño y la declara a través de setSupportActionBar()
. Luego, 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 y un menú independientes para un Fragmento específico , puede hacer lo siguiente:
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)
}
}
Sí, es así de fácil. Ni siquiera es necesario anular 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 AppCompat
en su styles.xml
).
Estoy tratando de agregar un elemento al menú de opciones de un grupo de fragmentos.
He creado una nueva clase MenuFragment
y la extendí 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.
Archivo de menú:
<?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>
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 del 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;
}
Configurar el menú de opciones después de crear la vista de fragmentos funcionó bien para mí.
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
}
Debe utilizar 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);
}
En el menu.xml
debe agregar todos los elementos del menú. Luego puede ocultar elementos que no desea ver en la carga inicial.
menu.xml
<item
android:id="@+id/action_newItem"
android:icon="@drawable/action_newItem"
android:showAsAction="never"
android:visible="false"
android:title="@string/action_newItem"/>
Agregue setHasOptionsMenu(true)
en el método onCreate () para invocar los elementos del menú en su clase de Fragmento.
FragmentClass.java
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
No es necesario volver a anular onCreateOptionsMenu
en tu clase de Fragmento nuevamente. Los elementos del menú se pueden cambiar (agregar / eliminar) al reemplazar el método onPrepareOptionsMenu
disponible en Fragmento.
@Override
public void onPrepareOptionsMenu(Menu menu) {
menu.findItem(R.id.action_newItem).setVisible(true);
super.onPrepareOptionsMenu(menu);
}
En la carpeta del menú, cree un archivo .menu xml y agregue este 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" />
En tu clase de fragmentos superan 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 xml de menú 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
}
});
}
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);
}
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
<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>
He tenido el mismo problema, mis fragmentos eran páginas de un ViewPager. La razón por la que estaba sucediendo es que estaba usando el administrador de fragmentos secundarios en lugar del administrador de fragmentos de soporte de actividades al crear una instancia de FragmentPagerAdapter.
Llame al super 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 las declaraciones de registro en el código para ver si no se está llamando al método o si el código no está siendo modificado por su código.
También asegúrese de que está llamando SetHasOptionsMenu
en onCreate
para notificar al fragmento que debería participar en el manejo del menú de opciones.
Me estaba volviendo loca porque ninguna de las respuestas aquí funcionaba para mí.
Para mostrar el menú al que tenía 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 setSupportActionBar(toolbar)
. Recordar: su clase de actividad debe extender la AppCompatActivity.
Espero que esta respuesta te ayude.
Mi problema fue ligeramente diferente. Hice todo bien. Pero estaba heredando la clase incorrecta para la actividad que aloja el fragmento.
Entonces, para ser claro, si está anulando onCreateOptionsMenu(Menu menu, MenuInflater inflater)
en el fragmento, asegúrese de que la clase de actividad que alberga este fragmento herede android.support.v7.app.ActionBarActivity
(en caso de que quiera apoyar por debajo de la API nivel 11).
Heredaba el android.support.v4.app.FragmentActivity
para soportar el nivel de API por debajo de 11.
Si encuentra que no se está invocando el método onCreateOptionsMenu(Menu menu, MenuInflater inflater)
, asegúrese de llamar a lo siguiente desde el método onCreate(Bundle savedInstanceState)
del Fragmento:
setHasOptionsMenu(true)
Si quieres añadir 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);
}
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, quizás tu tema de Android no sea compatible con la barra de acción. Abra AndroidManifest.xml y establezca el valor para android:theme
con el tema de la barra de acción de soporte :
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/Theme.AppCompat">
Tu código está bien. Solo faltaba el super 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);
}
Tuve el mismo problema, pero creo que es mejor resumir e introducir el último paso para que funcione:
Agregue el método setHasOptionsMenu (true) en el método
onCreate(Bundle savedInstanceState)
su Fragmento.Reemplace los
onCreateOptionsMenu(Menu menu, MenuInflater inflater)
(si desea hacer algo diferente en el menú de su Fragmento) yonOptionsItemSelected(MenuItem item)
en su Fragmento.Dentro del método de actividad
onOptionsItemSelected(MenuItem item)
, asegúrese de devolver el valor falso cuando la acción del elemento menu se implementaría en el método del fragmentoonOptionsItemSelected(MenuItem item)
.
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;
}
Una cosa agregaría a esto y la razón por la que no funcionaba para mí.
Es similar a la respuesta de Napster.
¡Asegúrese de que la actividad de alojamiento de su fragmento amplíe
AppCompatActivity
, noFragmentActivity
!public class MainActivity extends AppCompatActivity { }
De la Documentation referencia de Google para FragmentActivity:
Nota: Si desea implementar una actividad que incluya una barra de acción, debe usar la clase ActionBarActivity, que es una subclase de esta, así que le permite usar las API de fragmentos en el nivel 7 de API y superior.
Para actualizar la respuesta de Napster:
ActionBarActivity
ahora está en desuso, useAppCompatActivity
enAppCompatActivity
lugar.Al usar
AppCompatActivity
, también asegúrese de configurar "el tema de la actividad enTheme.AppCompat
o un tema similar" (Google Doc).
Nota: android.support.v7.app.AppCompatActivity
es una subclase de la clase android.support.v4.app.FragmentActivity
(consulte el AppCompatActivity referencia AppCompatActivity ).
en su método onCreate agregue setHasOptionMenu ()
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
Luego anula tu 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);
}