(Obsoleto) Fragmento onOptionsItemSelected que no se llama

82

EDITAR: Esta pregunta fue para la barra de acciones de Sherlock obsoleta. La biblioteca de soporte de Android debería usarse ahora

He agregado una opción de menú de la barra de acción llamada compartir para mi fragmentque aparece pero el evento de selección no se detecta

Lo estoy agregando así

@Override
public void onCreateOptionsMenu (Menu menu, MenuInflater inflater) {
    MenuItem item = menu.add(0, 7,0, R.string.share);
    item.setIcon(R.drawable.social_share).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}

Tratando de capturarlo tanto en el fragmentcomo en el fragment activitysimilar

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) {
        case 7:
            Intent share = new Intent(Intent.ACTION_SEND);
            share.setType("text/plain");
            share.putExtra(Intent.EXTRA_TEXT, "I'm being sent!!");
            startActivity(Intent.createChooser(share, "Share Text"));
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

y tengo setHasOptionsMenu(true);en el onCreate().

usuario1634451
fuente

Respuestas:

145

Los mismos problemas me pasaron a mí:

Los eventos onMenuItemSelected no se llamaron en Fragment

Google buscado no puede encontrar una solución, y agregar el método onMenuItemSelected en FragmentActivity no lo resuelve.

Finalmente, resuélvalo siguiendo la referencia a http://developer.android.com/guide/topics/ui/actionbar.html

Nota: Si agregó el elemento de menú de un fragmento, a través de la devolución de llamada onCreateOptionsMenu de la clase Fragment, el sistema llama al método onOptionsItemSelected () respectivo para ese fragmento cuando el usuario selecciona uno de los elementos del fragmento. Sin embargo, la actividad tiene la oportunidad de manejar el evento primero, por lo que el sistema llama a onOptionsItemSelected () en la actividad antes de llamar a la misma devolución de llamada para el fragmento.

Lo que significa que solo si no tiene ese controlador de elementos de menú en onOptionsItemSelected () en la actividad, se llamará a onOptionsItemSelected () en el fragmento.

Codifique de la siguiente manera ----- Elimine el controlador para R.action.add en FragmentActivity):

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) {
        case android.R.id.home:
            popBackStack();             
            return true;        
        case R.id.action_search:
            searchAction();
            return true;
        case R.id.action_logout:
            userLogout();
            return true;
        //case R.id.action_add:
            //return true;    
        default:
            return super.onOptionsItemSelected(item);
    }   
}

Y el controlador de R.action.add en Fragment se ve así:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    Log.d("onOptionsItemSelected","yes");
    switch (item.getItemId()) {
        case R.id.action_add:
            add();
            return true;    
        default:
            return super.onOptionsItemSelected(item);
    }
}

Finalmente, recuerde agregar

    setHasOptionsMenu(true);

en su método onCreate en Fragmento

Felixqk
fuente
12
Para mí, para interceptar el clic del menú en el fragmento, tuve que devolver "falso" en el onOptionsItemSelected de FragmentActivity y en el onOptionsItemSelected del fragmento, hacer el comportamiento deseado.
Edison Santos
1
fragmento con setHasOptionsMenu (verdadero); en onCreate y el método onOptionsItemSelected booleano público (elemento MenuItem) {} hizo la magia
Moisés
@Felixqk Tengo un problema como este con Fragments. Tengo dos fragmentos. Pero no se llama a OnOptionsSelectedItem del fragmento 2. El fragmento 2 muestra la opción de menú del fragmento 1.
Roon13
@ Roon13 Elimina super.onCreateOptionsMenu; del onCreateOptionsMenu del fragmento. + setHasOptionsMenu (verdadero); funcionó para mí sin eliminar Activity onOptionsItemSelected.
ahmadalibaloch
129

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

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

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

  3. Dentro del onOptionsItemSelected(MenuItem item)método de su actividad , asegúrese de regresar falsecuando la acción del elemento del menú se implementaría en el onOptionsItemSelected(MenuItem item)método de 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;
}
Marco HC
fuente
6
return falseen Activity onOptionItemSelectedes la clave. simplemente reemplacereturn super.onOptionItemSelected(item);
Youngjae
1
Funciona perfectamente. Gracias Marco.
Rajeev Sahu
2
Gran respuesta. Debes cambiar onCreateOptionsMenu (menú Menú) a onCreateOptionsMenu (menú Menú, Inflador MenuInflater) cuando está en un fragmento
Chris Sprague
1
Es una gran solucion. Thnakx Marco HC
Darsh Patel
1
¡Gran solución mi amigo! ¡Graciassss!
Han Tran
5

He notado que la solución que la gente le dio fue implementar el código para su elemento de menú en la actividad en lugar del fragmento. Creo que se verá mucho más organizado si hubiera implementado el código en el fragmento en lugar de la actividad porque, en mi opinión, se ve mejor. Para hacerlo, haga lo siguiente:

Actividad

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.menu, menu);      
        return true;
    }

 @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {            
        switch (item.getItemId())
        {
            case R.id.SomeIDInTheMenueOfTheActivity:
            {
               //something();
                break;
            }
            default:
             //do something default and add the code under : 
             return super.onOptionsItemSelected(item);
        }
        return true;
    }

Fragmento

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

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

     @Override
        public boolean onOptionsItemSelected(MenuItem item)
        {
            switch (item.getItemId())
            {           
                case R.id.SomeIDInFragmentMenue:
                {             
                    break;
                }

                default:
                    return super.onOptionsItemSelected(item);
            }

            return true;
        }

Ahora las líneas (y los me gusta): "return super.onOptionsItemSelected (item);" en la actividad y el fragmento son súper importantes, porque como si siguiera el código en la depuración, verá que las funciones de eventos del menú se llamarán primero en la Actividad, y si el elemento no coincide con los ID en el interruptor de la actividad- caso, la línea degault: "super.onOptionsItemSelected (item);" llamará a la función onOptionsItemSelected en el fragmento, como queríamos. (si tiene muchos fragmentos, asegúrese de incluir esa línea también, ya que la jerarquía de llamadas puede ser algo complicada).

Malfonde
fuente
2

Estoy usando actionbarsherlock. Esto funcionó para mí:

1) Crear menú dummy_menu.xml

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

<menu xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="match_parent" android:layout_width="fill_parent" >
<item
      android:title=""
      android:showAsAction="never"
      android:id="@+id/dummyMenu"
        />

2) En actividad, infle el menú de esta manera:

@Override
public boolean onCreateOptionsMenu(com.actionbarsherlock.view.Menu menu) {
    com.actionbarsherlock.view.MenuInflater inflater = getSupportMenuInflater();
   inflater.inflate(R.menu.dummy_menu,menu);
   return super.onCreateOptionsMenu(menu);
}

3) En los fragmentos onCreateView, llame a setHasOptionsMenu (verdadero) y anule onCreateOptionsMenu y onOptionsItemSelected también oculte el dummyMenu así (en fragmento)

    @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.fragment_actions, menu);
    MenuItem item = menu.findItem(R.id.dummyMenu);
    item.setVisible(false);
    super.onCreateOptionsMenu(menu, inflater);
}

Espero que ayude a alguien.

okkko
fuente
2

Editar para el uso de sherlock de la barra de acciones

Tuve que usar

public boolean onMenuItemSelected(int featureId, MenuItem item) {

en la actividad principal para capturar el elemento del menú

usuario1634451
fuente
El mismo problema y se solucionó para mí también gracias. ¿Puedes decir por qué onOptionItemSelected no funcionó?
nadeem gc
Porque la barra de acciones de
Sherlock
Cambie onMenuItemSelected para llamar a onOptionItemSelected para que su código funcione al pasar de ABS a appcompatlib
slott
1
@nadeemgc, la razón por la que no funciona es porque Android conoce dos tipos de menús: menú de opciones y menú contextual. Actionbar Sherlock usa el menú contextual, que llama en onContextItemSelectedlugar de onOptionsItemSelected. El onMenuItemSelectedsimplemente reenvía el clic con el método correcto, por lo que parece funcionar mejor.
Amru E.
@AmruE. Gracias, será útil en el futuro.
nadeem gc
2

es tan simple que puede hacer eso en su fragmento para asegurarse de que su acción se escuche correctamente:

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

Tuve este problema. Fue porque estaba superando el método equivocado

onOptionsItemSelected (elemento com.actionbarsherlock.view.MenuItem) es lo que utilicé.

¡Asegúrate de usar el correcto!

Barrie Galitzky
fuente
0

No se está encadenando a la superclase en los métodos de actividad. Haga que onCreateOptionsMenu () devuelva super.onCreateOptionsMenu (menú), y que onOptionsItemSelected () devuelva super.onOptionsItemSelected (elemento) (excepto el elemento que está manejando, que debe devolver verdadero para indicar que ha manejado el evento)

Divyesh V.Murani
fuente
0

debe agregar este código en la toolbar.bringToFront();siguiente barra de herramientas en su actividad

 public class MainActivity extends AppCompatActivity {
     protected void onCreate(Bundle savedInstanceState) {
        ...

        Toolbar toolbar = findViewById(R.id.toolbar);
        toolbar.setTitle("Yazd");
        setSupportActionBar(toolbar);
        toolbar.bringToFront(); // <<= add here
         ...
Mahdi Afkhami
fuente