(Veraltet) Fragment onOptionsItemSelected wird nicht aufgerufen


82

EDIT: Diese Frage war für die veraltete Sherlock-Aktionsleiste. Stattdessen sollte jetzt die Android-Unterstützungsbibliothek verwendet werden

Ich habe eine Menüoption in der Aktionsleiste mit dem Namen "Freigabe für meine" hinzugefügt, fragmentdie angezeigt wird, aber das Auswahlereignis wird nicht abgefangen

Ich füge es so hinzu

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

Der Versuch, es sowohl in der Art fragmentals auch in der fragment activityArt zu erfassen

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

und ich habe setHasOptionsMenu(true);in der onCreate().

Antworten:


145

Die gleichen Probleme sind mir passiert:

onMenuItemSelected-Ereignisse wurden in Fragment nicht aufgerufen

Durchsuchtes Google kann keine Lösung finden, und die Methode onMenuItemSelected in FragmentActivity löst sie nicht.

Beheben Sie das Problem schließlich, indem Sie dem Verweis auf http://developer.android.com/guide/topics/ui/actionbar.html folgen

Hinweis: Wenn Sie das Menüelement aus einem Fragment über den onCreateOptionsMenu-Rückruf der Fragmentklasse hinzugefügt haben, ruft das System die entsprechende onOptionsItemSelected () -Methode für dieses Fragment auf, wenn der Benutzer eines der Elemente des Fragments auswählt. Die Aktivität erhält jedoch die Möglichkeit, das Ereignis zuerst zu behandeln, sodass das System onOptionsItemSelected () für die Aktivität aufruft, bevor derselbe Rückruf für das Fragment aufgerufen wird.

Dies bedeutet nur, dass onOptionsItemSelected () für das Fragment aufgerufen wird, wenn Sie diesen Menüelement-Handler in onOptionsItemSelected () für die Aktivität nicht haben.

Code wie folgt ----- Entfernen Sie den Handler für R.action.add auf 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);
    }   
}

Und der Handler für R.action.add auf Fragment sieht folgendermaßen aus:

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

Denken Sie zum Schluss daran, hinzuzufügen

    setHasOptionsMenu(true);

in Ihrer onCreate-Methode in Fragment


12
Um das Menü abzufangen, klicken Sie auf das Fragment. Ich musste "false" für das onOptionsItemSelected der FragmentActivity und für das onOptionsItemSelected des Fragments zurückgeben und das gewünschte Verhalten ausführen.
Edison Santos

1
Fragment mit setHasOptionsMenu (true); in onCreate und public boolean onOptionsItemSelected (MenuItem item) {} Methode hat die Magie
Moisés

@ Felixqk Ich habe ein solches Problem mit Fragmenten. Ich habe zwei Fragmente. Das OnOptionsSelectedItem von Fragment 2 wird jedoch nicht aufgerufen. Fragment 2 zeigt die Menüoption von Fragment 1.
Roon13

@ Roon13 Entferne das super.onCreateOptionsMenu; aus dem onCreateOptionsMenu des Fragments. + setHasOptionsMenu (true); hat für mich gearbeitet, ohne Activity onOptionsItemSelected zu entfernen.
Ahmadalibaloch

129

Ich hatte das gleiche Problem, aber ich denke, es ist besser, den letzten Schritt zusammenzufassen und einzuführen, damit es funktioniert:

  1. Fügen Sie der setHasOptionsMenu(true)Methode Ihres Fragments eine onCreate(Bundle savedInstanceState)Methode hinzu.

  2. Überschreiben Sie onCreateOptionsMenu(Menu menu, MenuInflater inflater)(wenn Sie im Menü Ihres Fragments etwas anderes tun möchten) und onOptionsItemSelected(MenuItem item)Methoden in Ihrem Fragment.

  3. Stellen Sie in der onOptionsItemSelected(MenuItem item)Methode Ihrer Aktivität sicher, dass Sie zurückkehren, falsewenn die Menüelementaktion in der onOptionsItemSelected(MenuItem item)Methode von Fragment implementiert wird.

Ein Beispiel:

Aktivität

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

Fragment

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

6
return falseon Activity's onOptionItemSelectedist der Schlüssel. einfach ersetzenreturn super.onOptionItemSelected(item);
Youngjae

1
Perfekt funktionieren. Danke Marco.
Rajeev Sahu

2
Gute Antwort. Sie sollten onCreateOptionsMenu (Menü Menü) in onCreateOptionsMenu (Menü Menü, MenuInflater Inflater) ändern, wenn es in einem Fragment ist
Chris Sprague

1
Es ist eine großartige Lösung. Thnakx Marco HC
Vipul Patel

1
Tolle Lösung, mein Freund! Danke!
Han Tran

5

Ich habe festgestellt, dass die Lösung, die Ihnen gegeben wurde, darin bestand, den Code für Ihr Menüelement in der Aktivität und nicht das Fragment zu implementieren. Ich denke, es wird viel besser aussehen, wenn Sie den Code in das Fragment implementiert haben, anstatt die Aktivität, weil es meiner Meinung nach besser aussieht. Gehen Sie dazu wie folgt vor:

Aktivität

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

Fragment

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

Nun die Zeilen (und dergleichen): "return super.onOptionsItemSelected (item);" in der Aktivität und Fragment sind sehr wichtig, denn als ob Sie dem Code beim Debuggen folgen würden, werden Sie sehen, dass die Menüereignisfunktionen zuerst in der Aktivität aufgerufen werden und wenn das Element nicht mit den IDs im Schalter der Aktivität übereinstimmt. In diesem Fall die Degault-Zeile: "super.onOptionsItemSelected (item);" ruft die Funktion onOptionsItemSelected für das Fragment auf, wie wir wollten. (Wenn Sie viele Fragmente haben, stellen Sie sicher, dass auch diese Zeile enthalten ist, da die aufrufende Hirarchie etwas kompliziert sein kann).


2

Ich benutze Actionbarsherlock. Das hat bei mir funktioniert:

1) Erstellen Sie das 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) Bei Aktivität das Menü wie folgt aufblasen:

@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) Rufen Sie in Fragmenten onCreateView setHasOptionsMenu (true) auf und überschreiben Sie onCreateOptionsMenu und onOptionsItemSelected. Verstecken Sie auch das DummyMenu wie folgt (im Fragment).

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

Hoffe es hilft jemandem.


2

Bearbeiten für Sherlock in der Aktionsleiste

Ich musste benutzen

public boolean onMenuItemSelected(int featureId, MenuItem item) {

in der Hauptaktivität, um den Menüpunkt zu erfassen


Das gleiche Problem und es wurde auch für mich behoben, danke. Können Sie erkennen, warum onOptionItemSelected nicht funktioniert hat?
Nadeem GC

Weil die Sherlock-
Aktionsleiste

Ändern Sie onMenuItemSelected, um onOptionItemSelected aufzurufen, damit Ihr Code funktioniert, wenn Sie von ABS zu appcompatlib wechseln
Slott

1
@nadeemgc Der Grund, warum es nicht funktioniert, ist, dass Android zwei Arten von Menüs kennt: Optionsmenü und Kontextmenü. Aktionsleiste Sherlock verwendet das Kontextmenü, das onContextItemSelectedanstelle von aufruft onOptionsItemSelected. Das onMenuItemSelectedleitet den Klick einfach an die richtige Methode weiter, weshalb es besser zu funktionieren scheint.
Amru E.

@ AmruE. Vielen Dank, es wird in Zukunft hilfreich sein.
Nadeem GC

2

Es ist so einfach, dass Sie dies in Ihrem Fragment tun können, um sicherzustellen, dass Ihre Aktion korrekt zuhört:

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

0

Ich hatte dieses Problem. Es war, weil ich die falsche Methode überschrieb

onOptionsItemSelected (com.actionbarsherlock.view.MenuItem-Element) habe ich verwendet.

Stellen Sie sicher, dass Sie die richtige verwenden!


0

Sie sind in den Aktivitätsmethoden nicht an die Oberklasse gekettet. Bitte lassen Sie onCreateOptionsMenu () super.onCreateOptionsMenu (Menü) zurückgeben und onOptionsItemSelected () super.onOptionsItemSelected (item) zurückgeben (mit Ausnahme des von Ihnen bearbeiteten Elements, das true zurückgeben sollte, um anzuzeigen, dass Sie das Ereignis behandelt haben).


0

Sie müssen diesen Code als toolbar.bringToFront();nächstes in der Symbolleiste Ihrer Aktivität hinzufügen

 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
         ...
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.