So fügen Sie Fragment in Android ein Optionsmenü hinzu

399

Ich versuche, aus einer Gruppe von Fragmenten ein Element zum Optionsmenü hinzuzufügen.

Ich habe eine neue MenuFragmentKlasse erstellt und diese für die Fragmente erweitert, in die ich den Menüpunkt aufnehmen möchte. Hier ist der Code:

Java:

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

Kotlin:

class MenuFragment : Fragment {

    lateinit var fav: MenuItem

    override fun onCreate(savedInstanceState: Bundle) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        fav = menu.add("add");
        fav.setIcon(R.drawable.btn_star_big_off);
    }
}

Aus irgendeinem Grund onCreateOptionsMenuscheint das nicht zu laufen.

Misterbassman
quelle
Vielleicht eine dumme Frage ... Sie drücken die Menütaste richtig?
Ovidiu Latcu
2
..lol ... ja ich habe die Menütaste gedrückt, ich habe es auch mit und ohne versucht: fav.setShowAsAction (MenuItem.SHOW_AS_ACTION_ALWAYS);
Misterbassman
Hallo, vielleicht hilft dir dieser Thread oder überprüfe die API-Demo auf ein funktionierendes Beispiel.
kamy

Antworten:

605

Nennen Sie die Supermethode:

Java:

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

Kotlin:

    override fun void onCreate(savedInstanceState: Bundle) {
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        // TODO Add your menu entries here
        super.onCreateOptionsMenu(menu, inflater)
    }

Fügen Sie Protokollanweisungen in den Code ein, um festzustellen, ob die Methode nicht aufgerufen wird oder ob das Menü nicht durch Ihren Code geändert wird.

Auch stellen Sie sicher , rufen setHasOptionsMenu(boolean)in onCreate(Bundle)das Fragment zu informieren , dass es in Optionsmenü Handhabung teilnehmen sollten.

Kuffs
quelle
2
Vielen Dank für die Hilfe, ich habe die Super-Methode hinzugefügt und festgestellt, dass ich @Override entfernt habe, also habe ich dies wieder hinzugefügt. Eclipse hat einen Fehler ausgegeben, sodass ich den MenuInflater ersetzt habe, um android.view.MenuInflater zu importieren. anstelle von android.support.v4.view.MenuInflater importieren; und jetzt funktioniert alles
Misterbassman
183
setHasOptionsMenu (true) im onCreate des Fragments nicht aufzurufen, hat mich jetzt zweimal
erwischt
7
Ich habe meine Aktivität auf ein Fragment übertragen und bin auf dieses Problem gestoßen. Die Methodensignatur wurde von public boolean in public void geändert, und auch die Argumente haben sich geändert. Beachten Sie dies unbedingt!
you786
14
Beachten Sie, dass Fragment.onCreateOptionsMenu (Menu, MenuInflater) eine leere Methode ist, sodass der Aufruf von super überhaupt nicht erforderlich ist. Der einzige Fehler war hier die falsche Methodensignatur und möglicherweise ein fehlendes setHasOptionsMenu () in onCreate ()
cmende
6
Ersetzen Sie super.onCreateOptionsMenu durch inflater.inflate (R.menu.menu_custom, menu);
Code_Worm
197

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 Methode Ihres Fragments die onCreate(Bundle savedInstanceState)Methode setHasOptionsMenu (true) 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. In deinem onOptionsItemSelected(MenuItem item) der Methode Aktivität sicher, dass Sie false zurückgeben, wenn die Menüelementaktion in der onOptionsItemSelected(MenuItem item)Fragment-Methode 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;
}
Marco HC
quelle
2
Nur fehlte setHasOptionsMenu(true);Danke
Chad Bingham
1
Auf einem viewPager auf einigen Geräten wird das Menü nur beim zweiten Mal angezeigt, wenn Sie zum Fragment gehen
Roel
3
@Marco HC Ihr Code funktioniert gut. Aber was ist, wenn ich einen Teil des Menüs für Aktivität oder Fragment ausblenden möchte? Sie haben erwähnt, wo welches Optionsmenü implementiert werden soll (In Aktivität und Fragment). Aber was ist, wenn ich ein Menü ausblenden möchte?
Shreyash Mahajan
@iDroidExplorer behält einfach einen Verweis auf dieses Menüelement bei und setzt die Sichtbarkeit auf verschwunden oder unsichtbar. Ist das deine Frage?
Marco HC
@iDroidExplorer Ich habe seinen Code ausprobiert und weiß nicht wie, aber er versteckt automatisch das Menü, wenn ich zu anderen Fragmenten wechsle.
Noor Ali Butt
156

Wenn Sie feststellen, dass die onCreateOptionsMenu(Menu menu, MenuInflater inflater)Methode nicht aufgerufen wird, rufen Sie in der Methode des Fragments Folgendes auf onCreate(Bundle savedInstanceState):

setHasOptionsMenu(true)
Matthew Blackford
quelle
Es gibt mir Fehler wie NullPointerException
Pratik Butani
2
Guter Punkt. Ich habe die setHasOptionMenu-Methode von der statischen newInstance-Methode aufgerufen. Da ich mein Fragment nur anhängte, als savedInstanceState null war, wurde das Menü nicht erstellt, wenn die Bildschirmkonfiguration geändert wurde. Die onCreate-Methode des Fragments ist der richtige Ort, an dem setHasOptionMenu auf true gesetzt wird.
Argenkiwi
1
Ich verwende ein Toolbarund musste rufen setHasOptionsMenu(true)in onCreateView()statt , onCreate()um es getan.
CLOUGH
60

Wenn Sie ein benötigen menu, um webviewein bestimmtes Objekt zu aktualisieren Fragment, können Sie Folgendes verwenden:

Fragment :

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;

}

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>
CONvid19
quelle
31

TL; DR

Verwenden Sie die android.support.v7.widget.Toolbarund tun Sie einfach:

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

Standalone-Symbolleiste

Die meisten der vorgeschlagenen Lösungen setHasOptionsMenu(true)funktionieren nur, wenn die übergeordnete Aktivität die Symbolleiste im Layout hat und über deklariert setSupportActionBar(). Dann können die Fragmente an der Menüpopulation dieser genauen ActionBar teilnehmen :

Fragment.onCreateOptionsMenu (): Initialisiert den Inhalt des Standardoptionsmenüs des Fragment-Hosts.

Wenn Sie eine eigenständige Symbolleiste und ein Menü für ein bestimmtes Fragment wünschen , können Sie Folgendes tun:

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

Ja, so einfach ist das. Sie müssen nicht einmal überschreiben onCreate()oder onCreateOptionsMenu().

PS: Dies funktioniert nur mit android.support.v4.app.Fragmentund android.support.v7.widget.Toolbar(verwenden Sie auch AppCompatActivityein AppCompatThema in Ihrem styles.xml).

Marius
quelle
1
hat mir sehr geholfen
brahmy adigopula
23

In menu.xmlsollten Sie alle Menüpunkte hinzufügen. Anschließend können Sie Elemente ausblenden, die beim ersten Laden nicht angezeigt werden sollen.

menu.xml

<item
    android:id="@+id/action_newItem"
    android:icon="@drawable/action_newItem"
    android:showAsAction="never"
    android:visible="false"
    android:title="@string/action_newItem"/>

Fügen Sie setHasOptionsMenu(true)die onCreate () -Methode hinzu, um die Menüelemente in Ihrer Fragment-Klasse aufzurufen.

FragmentClass.java

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

Sie müssen onCreateOptionsMenuIhre Fragment-Klasse nicht erneut überschreiben . Menüelemente können durch Überschreiben der onPrepareOptionsMenuin Fragment verfügbaren Methode geändert (Hinzufügen / Entfernen) werden .

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

}
Parinda Rajapaksha
quelle
16

Sie müssen menu.clear () verwenden, bevor Sie Menüs aufblasen.

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

und

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }
Spl2nky
quelle
1
Dies ist richtig, wenn Sie unterschiedliche Menüs in unterschiedlichen Fragmenten möchten und Fragmente hinzufügen, anstatt sie zu ersetzen.
Akshay Mahajan
Vielen Dank! menu.clear () hilft mir, die Menüoption von Aktivität zu entfernen.
Kimcy929
13

In meinem Fall sind hier die Schritte.

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

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

Schritt 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);
}
Harry Zhang
quelle
Ich hatte bereits ein Menü für die Hauptaktivität mit dem menu.clear()zuvor gelöschten Menü. Arbeitete für mich :)
Anbuselvan Rocky
8

Wenn Sie Ihr Menü benutzerdefiniert hinzufügen möchten

@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);
}
Ezequiel García
quelle
Was ist, wenn es eine Registerkartenansicht gibt und Sie für jedes Fragment unterschiedliche Menüs aufblasen möchten?
Jainam Jhaveri
7

Ich hatte das gleiche Problem, meine Fragmente waren Seiten eines ViewPagers. Der Grund dafür ist, dass ich beim Instanziieren von FragmentPagerAdapter eher den untergeordneten Fragmentmanager als den Aktivitätsunterstützungsfragmentmanager verwendet habe.

farid_z
quelle
3

Menü Datei:

<?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>

Aktivitätscode:

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

Fragmentcode:

@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;
}
Suyog Gunjal
quelle
3

Ihr Code ist in Ordnung. In der Methode fehlte nur der Super:

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

Ich wurde verrückt, weil keine der Antworten hier für mich funktionierte.

Um das Menü anzuzeigen, musste ich anrufen: setSupportActionBar(toolbar)

Erledigt!

Hinweis: Wenn sich Ihre toolbarAnsicht nicht im selben Aktivitätslayout befindet, können Sie den obigen Aufruf nicht direkt von Ihrer Aktivitätsklasse aus verwenden. In diesem Fall müssen Sie diese Aktivität von Ihrer Fragmentklasse abrufen und dann die aufrufen setSupportActionBar(toolbar). Denken Sie daran: Ihre Aktivitätsklasse sollte die AppCompatActivity erweitern.

Hoffe, dass diese Antwort Ihnen hilft.

Filipe Brito
quelle
1

Das Einstellen des Optionsmenüs nach dem Erstellen der Fragmentansicht hat bei mir gut funktioniert.

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

Mein Problem war etwas anders. Ich habe alles richtig gemacht. Aber ich habe die falsche Klasse für die Aktivität geerbt, die das Fragment hostet.

Wenn Sie onCreateOptionsMenu(Menu menu, MenuInflater inflater)das Fragment überschreiben , stellen Sie sicher, dass Ihre Aktivitätsklasse, die dieses Fragment hostet, erbtandroid.support.v7.app.ActionBarActivity (falls Sie unter API-Ebene 11 unterstützen möchten).

Ich habe die android.support.v4.app.FragmentActivityAPI-Stufe unter 11 geerbt .

Krishna Deepak
quelle
1

Eine Sache würde ich hinzufügen und den Grund, warum es bei mir nicht funktionierte.

Es ist ähnlich wie Napsters Antwort.

  1. Stellen Sie sicher, dass die Hosting-Aktivität Ihres Fragments erweitert wird AppCompatActivity, nicht FragmentActivity!

    public class MainActivity extends AppCompatActivity {
    
    }

    Von der Google Referenz - Dokumentation für FragmentActivity:

    Hinweis: Wenn Sie eine Aktivität implementieren möchten, die eine Aktionsleiste enthält, sollten Sie stattdessen die ActionBarActivity-Klasse verwenden, die eine Unterklasse dieser Klasse ist, sodass Sie Fragment-APIs auf API-Ebene 7 und höher verwenden können.

  2. ActionBarActivityVerwenden Sie AppCompatActivitystattdessen Napsters Antwort, die jetzt veraltet ist .

  3. AppCompatActivityStellen Sie bei der Verwendung außerdem sicher, dass Sie "das Aktivitätsthema auf Theme.AppCompatoder ein ähnliches Thema" (Google Doc) festlegen .

Hinweis: android.support.v7.app.AppCompatActivityist eine Unterklasse der android.support.v4.app.FragmentActivityKlasse (siehe AppCompatActivity ref doc).

Bastien
quelle
1

Erstellen Sie in Ihrem Menüordner eine Menü-XML-Datei und fügen Sie diese XML hinzu

<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" />

Überschreiben Sie in Ihrer Fragmentklasse diese Methode und

implement SearchView.OnQueryTextListener    in your fragment class



@Override
 public void onViewCreated(View view, Bundle savedInstanceState) {    
  super.onViewCreated(view, savedInstanceState);
  setHasOptionsMenu(true);

}

Richten Sie jetzt einfach Ihre Menü-XML-Datei in der Fragmentklasse ein

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

}
pavel
quelle
0

Wenn alle oben genannten Funktionen nicht funktionieren, müssen Sie debuggen und sicherstellen, dass die Funktion onCreateOptionsMenu aufgerufen wurde (indem Sie ein Debug- oder Schreibprotokoll platzieren ...).

Wenn es nicht ausgeführt wird, unterstützt Ihr Android-Design möglicherweise die Aktionsleiste nicht. Öffnen AndroidManifest.xml und der Wert für die android:thememit Theme - Unterstützung Aktionsleiste :

 <activity
     android:name=".MainActivity"
     android:label="@string/app_name"
     android:theme="@style/Theme.AppCompat">
Grauer Wolf
quelle
0

Fügen Sie auf Ihrer onCreate- Methode setHasOptionMenu () hinzu.

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

Überschreiben Sie dann Ihr 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);
}
Ashana.Jackol
quelle