Come aggiungere il menu Opzioni al frammento in Android


399

Sto cercando di aggiungere un elemento al menu delle opzioni da un gruppo di frammenti.

Ho creato una nuova MenuFragmentclasse e l'ho estesa per i frammenti in cui desidero includere la voce di menu. Ecco il codice:

Giava:

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

Per qualche motivo onCreateOptionsMenusembra non funzionare.


forse una domanda stupida ... premi il pulsante menu giusto?
Ovidiu Latcu,

2
..lol ... sì, ho premuto il pulsante menu, l'ho provato anche con e senza: fav.setShowAsAction (MenuItem.SHOW_AS_ACTION_ALWAYS);
Misterbassman,

Ciao, forse questo thread ti aiuterà o controlla la demo di api per un esempio funzionante.
Kameny,

Risposte:


605

Chiama il metodo super:

Giava:

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

Inserisci le istruzioni di registro nel codice per vedere se il metodo non viene chiamato o se il menu non viene modificato dal codice.

Inoltre assicurarsi che si sta chiamando setHasOptionsMenu(boolean)in onCreate(Bundle)per notificare il frammento che dovrebbe partecipare nella gestione menu delle opzioni.


2
Grazie per l'aiuto, ho aggiunto il metodo super e mi sono reso conto di aver rimosso @Override, quindi l'ho aggiunto di nuovo, eclipse ha generato un errore, quindi ho sostituito MenuInflater per importare android.view.MenuInflater; invece di importare android.support.v4.view.MenuInflater; e ora tutto funziona
misterbassman,

183
non chiamare setHasOptionsMenu (true) in on the Fragment's onCreate mi ha ottenuto due volte ora
joshkendrick,

7
Stavo trasferendo la mia attività su un frammento e ho riscontrato questo problema. La firma del metodo è cambiata da pubblico booleano a vuoto pubblico e anche gli argomenti sono cambiati. Assicurati di prenderne nota!
tu786

14
Nota che Fragment.onCreateOptionsMenu (Menu, MenuInflater) è un metodo vuoto, quindi non è necessario chiamare super. L'unico errore qui era la firma del metodo sbagliata e forse un set mancanteHasOptionsMenu () in onCreate ()
cmende

6
Sostituisci super.onCreateOptionsMenu con inflater.inflate (R.menu.menu_custom, menu);
Code_Worm,

197

Ho avuto lo stesso problema, ma penso che sia meglio riassumere e introdurre l'ultimo passaggio per farlo funzionare:

  1. Aggiungi il metodo setHasOptionsMenu (true) nel metodo del tuo frammento onCreate(Bundle savedInstanceState).

  2. Sostituisci onCreateOptionsMenu(Menu menu, MenuInflater inflater)(se vuoi fare qualcosa di diverso nel menu del tuo frammento) e onOptionsItemSelected(MenuItem item)metodi nel tuo frammento.

  3. Nel onOptionsItemSelected(MenuItem item)metodo della tua attività, assicurati di restituire false quando l'azione della voce di menu verrà implementata nel onOptionsItemSelected(MenuItem item)metodo Fragment.

Un esempio:

Attività

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

Frammento

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

2
Mancava solo setHasOptionsMenu(true);Grazie
Chad Bingham,

1
Su un viewPager su alcuni dispositivi il menu viene mostrato solo la seconda volta che vai al frammento
Roel

3
@Marco HC il tuo codice funziona bene. E se volessi nascondere alcuni dei menu per Activity o per Fragment? Hai menzionato dove implementare quale menu di opzioni (In attività e frammento). E se volessi nascondere qualche menu?
Shreyash Mahajan

@iDroidExplorer tiene semplicemente un riferimento a quel MenuItem e imposta la visibilità su sparita o invisibile. È questa la tua domanda?
Marco HC

@iDroidExplorer Ho provato il suo codice e non so come, ma nasconde automaticamente il menu quando passo ad altri frammenti.
Noor Ali Butt

156

Se trovi che il onCreateOptionsMenu(Menu menu, MenuInflater inflater)metodo non viene invocato, assicurati di chiamare quanto segue dal onCreate(Bundle savedInstanceState)metodo del frammento :

setHasOptionsMenu(true)

Mi dà un errore come NullPointerException
Butani,

2
Buon punto. Stavo chiamando il metodo setHasOptionMenu dal metodo newInstance statico. Poiché stavo collegando il mio frammento solo quando saveInstanceState era null, quando la configurazione dello schermo cambiava il menu non veniva creato. Il metodo onCreate del frammento è il posto corretto in cui impostare setHasOptionMenu su true.
Argenkiwi,

1
Io sto usando un Toolbare ho dovuto chiamare setHasOptionsMenu(true)in onCreateView(), invece onCreate()di avere fatto.
CLOUGH,

60

Se hai bisogno di a menuper aggiornare uno webviewall'interno di uno specifico Fragment, puoi usare:

Frammento :

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>

31

TL; DR

Usa il android.support.v7.widget.Toolbare fai semplicemente:

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

Barra degli strumenti autonoma

La maggior parte delle soluzioni suggerite come setHasOptionsMenu(true)funzionano solo quando l' attività principale ha la barra degli strumenti nel suo layout e la dichiara tramite setSupportActionBar(). Quindi i frammenti possono partecipare alla popolazione di menu di questa esatta ActionBar :

Fragment.onCreateOptionsMenu (): inizializza il contenuto del menu delle opzioni standard dell'host Fragment.

Se si desidera una barra degli strumenti e un menu autonomi per un frammento specifico, è possibile effettuare le seguenti operazioni:

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ì, è così facile. Non è nemmeno necessario eseguire l'override onCreate()o onCreateOptionsMenu().

PS: Funziona solo con android.support.v4.app.Fragmente android.support.v7.widget.Toolbar(assicurati anche di usare AppCompatActivitye un AppCompattema nel tuo styles.xml).


1
mi ha davvero aiutato molto
brahmy adigopula il

23

Nel menu.xmldovresti aggiungere tutte le voci di menu. Quindi puoi nascondere gli elementi che non vuoi vedere nel caricamento iniziale.

menu.xml

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

Aggiungi setHasOptionsMenu(true)il metodo onCreate () per richiamare le voci di menu nella tua classe Fragment.

FragmentClass.java

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

Non è necessario eseguire onCreateOptionsMenunuovamente l' override nella classe Fragment. Le voci di menu possono essere modificate (Aggiungi / Rimuovi) sostituendo il onPrepareOptionsMenumetodo disponibile in Frammento.

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

}

16

È necessario utilizzare menu.clear () prima di gonfiare i menu.

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

e

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

1
Questo è corretto quando si desidera menu diversi in frammenti diversi e si stanno aggiungendo frammenti invece di sostituirli.
Akshay Mahajan,

Grazie! menu.clear () mi aiuta a rimuovere l'opzione di menu di Attività.
kimcy929,

13

Nel mio caso, ecco i passaggi.

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

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

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

Avevo già un menu sull'attività principale, usando il menu.clear()menu precedente cancellato. Ha funzionato per me :)
Anbuselvan Rocky,

8

Se vuoi aggiungere il tuo menu personalizzato

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

cosa succede se esiste una vista a schede e si desidera gonfiare menu diversi per ciascun frammento?
Jainam Jhaveri,

7

Ho avuto lo stesso problema, i miei frammenti erano pagine di un ViewPager. La ragione per cui stava accadendo è che stavo usando il gestore frammento figlio anziché il gestore frammento supporto attività durante l'istanza di FragmentPagerAdapter.


3

File del menu:

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

Codice attività:

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

Codice frammento:

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

3

Il tuo codice va bene. Nel metodo mancava solo il 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);
}

2

Stavo diventando pazzo perché nessuna delle risposte qui ha funzionato per me.

Per mostrare il menu che ho dovuto chiamare: setSupportActionBar(toolbar)

Fatto!

Nota: se la toolbarvista non è nello stesso layout di attività non è possibile utilizzare la chiamata sopra direttamente dalla propria classe di attività, in questo caso è necessario ottenere tale attività dalla propria classe di frammenti e quindi chiamare il setSupportActionBar(toolbar). Ricordare: la classe di attività dovrebbe estendere AppCompatActivity.

Spero che questa risposta ti aiuti.


1

L'impostazione del menu delle opzioni dopo aver creato la vista frammento ha funzionato bene per me.

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

1

Il mio problema era leggermente diverso. Ho fatto tutto bene. Ma ereditavo la classe sbagliata per l'attività che ospitava il frammento.

Quindi, per essere chiari, se si esegue onCreateOptionsMenu(Menu menu, MenuInflater inflater)l' override nel frammento, assicurarsi che la classe di attività che ospita questo frammento ereditiandroid.support.v7.app.ActionBarActivity (nel caso in cui si desideri supportare al di sotto del livello API 11).

Stavo ereditando il android.support.v4.app.FragmentActivitysupporto di livello API inferiore a 11.


1

Una cosa che vorrei aggiungere a questo e il motivo per cui non funzionava per me.

È simile alla risposta di Napster.

  1. Assicurati che l'attività di hosting del tuo frammento si estenda AppCompatActivity, non FragmentActivity!

    public class MainActivity extends AppCompatActivity {
    
    }

    Dalla documentazione di riferimento di Google per FragmentActivity:

    Nota: se si desidera implementare un'attività che include una barra delle azioni, è necessario utilizzare invece la classe ActionBarActivity, che è una sottoclasse di questa, in modo da poter utilizzare le API di frammento a livello di API 7 o superiore.

  2. Per aggiornare la risposta di Napster, ActionBarActivityora deprecata, usa AppCompatActivityinvece.

  3. Durante l'utilizzo AppCompatActivity, assicurati anche di impostare "il tema dell'attività su Theme.AppCompato un tema simile" (Google Doc).

Nota: android.support.v7.app.AppCompatActivityè una sottoclasse della android.support.v4.app.FragmentActivityclasse (consultare il documento ref di AppCompatActivity ).


1

Nella tua cartella menu crea un file XML .menu e aggiungi questo 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" />

Nella tua classe di frammenti sostituisci questo metodo e

implement SearchView.OnQueryTextListener    in your fragment class



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

}

Ora configura il tuo file xml di menu nella classe di frammenti

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

}

0

Se tutto quanto sopra non funziona, è necessario eseguire il debug e assicurarsi che sia stata chiamata la funzione onCreateOptionsMenu (posizionando il debug o scrivere il registro ...)

Se non viene eseguito, forse il tuo tema Android non supporta la barra delle azioni. Apri AndroidManifest.xml e imposta il valore android:themecon la barra delle azioni di supporto del tema :

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

0

sul vostro onCreate metodo add setHasOptionMenu ()

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

Quindi sovrascrivere il menu onCreateOptions

@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);
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.