La barra superiore dell'app fornisce una posizione coerente nella parte superiore della finestra dell'app per visualizzare le informazioni e le azioni della schermata corrente.
La proprietà della barra dell'app varia a seconda delle esigenze dell'app. Quando si utilizzano i frammenti, la barra dell'app può essere implementata come un elemento ActionBar
di proprietà dell'attività host o come barra degli strumenti all'interno del layout del frammento.
Se tutti i tuoi schermi utilizzano la stessa barra dell'app, sempre in alto e che si estende per tutta la larghezza dello schermo, utilizza una barra delle azioni fornita dal tema e ospitata dall'attività. L'utilizzo delle barre delle app a tema consente di mantenere un aspetto coerente e offre uno spazio in cui ospitare i menu opzioni e un pulsante Su.
Utilizza una barra degli strumenti ospitata dal frammento se vuoi un maggiore controllo su dimensioni, posizionamento e animazione della barra dell'app su più schermate. Ad esempio, potresti aver bisogno di una barra dell'app che comprimi o si estende solo per metà della larghezza dello schermo ed è centrata verticalmente.
Situazioni diverse richiedono approcci diversi, ad esempio per gonfiare i menu e rispondere all'interazione dell'utente. Capire i diversi approcci e utilizzare quello migliore per la tua app consente di risparmiare tempo e di garantire che l'app funzioni correttamente.
Gli esempi in questo argomento fanno riferimento a un ExampleFragment
che contiene
un profilo modificabile. Il frammento aumenta il seguente
menu definito XML nella barra dell'app:
<!-- sample_menu.xml -->
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_settings"
android:icon="@drawable/ic_settings"
android:title="@string/settings"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/action_done"
android:icon="@drawable/ic_done"
android:title="@string/done"
app:showAsAction="ifRoom|withText"/>
</menu>
Il menu contiene due opzioni: una per accedere alla schermata di un profilo e una per salvare le modifiche apportate al profilo.
Barra dell'app di proprietà dell'attività
La barra delle app è più comunemente utilizzata dall'attività dell'host. Quando la barra dell'app è di proprietà di un'attività, i frammenti possono interagire con la barra ignorando i metodi del framework richiamati durante la creazione dei frammenti.
Registrati con l'attività
Devi comunicare al sistema che il frammento della barra dell'app fa parte della compilazione del menu opzioni. Per farlo, chiama setHasOptionsMenu(true)
nel metodo onCreate(Bundle)
del frammento, come mostrato nell'esempio seguente:
Kotlin
class ExampleFragment : Fragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) } }
Java
public class ExampleFragment extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); } }
setHasOptionsMenu(true)
indica al sistema che il frammento
vuole ricevere callback relativi ai menu. Quando si verifica un evento relativo al menu, ad esempio un clic, il metodo di gestione degli eventi viene chiamato inizialmente nell'attività e poi nel frammento.
Tuttavia, non fare affidamento su questo ordine nella logica dell'applicazione. Se la stessa attività ospita più frammenti, ogni frammento può fornire opzioni di menu, nel qual caso l'ordine di callback dipende dall'ordine in cui vengono aggiunti i frammenti.
Amplia il menu
Per unire il menu a quello della barra dell'app, esegui l'override di onCreateOptionsMenu()
nel frammento. Questo metodo riceve l'attuale menu della barra dell'app e un
MenuInflater
come parametri. Utilizza il pulsante di gonfiaggio dei menu per creare un'istanza del menu del frammento, quindi uniscila al menu corrente, come mostrato nell'esempio seguente:
Kotlin
class ExampleFragment : Fragment() { ... override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { inflater.inflate(R.menu.sample_menu, menu) } }
Java
public class ExampleFragment extends Fragment { ... @Override public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { inflater.inflate(R.menu.sample_menu, menu); } }
La figura 2 mostra il menu aggiornato.
Gestire gli eventi di clic
Ogni attività e frammento che partecipa al menu opzioni
risponde ai tocchi. L'elemento onOptionsItemSelected()
del frammento riceve la voce di menu selezionata come parametro e restituisce un valore booleano che indica se viene consumato il tocco. Quando un'attività o un frammento restituisce true
da onOptionsItemSelected()
, nessun altro frammento partecipante riceverà il callback.
Nell'implementazione di onOptionsItemSelected()
, utilizza un'istruzione switch
in itemId
della voce di menu. Se l'elemento selezionato è tuo, gestisci il tocco in modo appropriato e restituisci true
per indicare che viene gestito l'evento di clic. Se l'elemento selezionato non è tuo, chiama l'implementazione super
. Per impostazione predefinita, l'implementazione super
restituisce false
per continuare l'elaborazione del menu.
Kotlin
class ExampleFragment : Fragment() { ... override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { R.id.action_settings -> { // Navigate to settings screen. true } R.id.action_done -> { // Save profile changes. true } else -> super.onOptionsItemSelected(item) } } }
Java
public class ExampleFragment extends Fragment { ... @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.action_settings: { // Navigate to settings screen. return true; } case R.id.action_done: { // Save profile changes. return true; } default: return super.onOptionsItemSelected(item); } } }
Modificare in modo dinamico il menu
Inserisci la logica per nascondere o mostrare un pulsante o modificare l'icona in onPrepareOptionsMenu()
.
Questo metodo viene richiamato subito prima della visualizzazione del menu.
Continuando con l'esempio precedente, il pulsante Salva dovrebbe essere invisibile finché l'utente non inizia a modificarlo e dovrebbe scomparire dopo il salvataggio. L'aggiunta di questa logica a onPrepareOptionsMenu()
rende
il menu presente correttamente:
Kotlin
class ExampleFragment : Fragment() { ... override fun onPrepareOptionsMenu(menu: Menu){ super.onPrepareOptionsMenu(menu) val item = menu.findItem(R.id.action_done) item.isVisible = isEditing } }
Java
public class ExampleFragment extends Fragment { ... @Override public void onPrepareOptionsMenu(@NonNull Menu menu) { super.onPrepareOptionsMenu(menu); MenuItem item = menu.findItem(R.id.action_done); item.setVisible(isEditing); } }
Quando devi aggiornare il menu, ad esempio quando un utente preme il pulsante Modifica per modificare le informazioni del profilo, chiama invalidateOptionsMenu()
sull'attività dell'host per richiedere che il sistema chiami onCreateOptionsMenu()
.
Dopo l'annullamento della convalida, puoi apportare gli aggiornamenti in onCreateOptionsMenu()
. Quando il menu aumenta, il sistema chiama onPrepareOptionsMenu()
e aggiorna il menu per riflettere lo stato attuale del frammento.
Kotlin
class ExampleFragment : Fragment() { ... fun updateOptionsMenu() { isEditing = !isEditing requireActivity().invalidateOptionsMenu() } }
Java
public class ExampleFragment extends Fragment { ... public void updateOptionsMenu() { isEditing = !isEditing; requireActivity().invalidateOptionsMenu(); } }
Barra dell'app di proprietà di un frammento
Se la maggior parte delle schermate dell'app non ha bisogno di una barra dell'app o se una
schermata richiede una barra dell'app diversa rispetto alle altre, puoi aggiungere un elemento
Toolbar
al
layout dei frammenti. Anche se puoi aggiungere un elemento Toolbar
in qualsiasi punto della gerarchia delle visualizzazioni del frammento, in genere lo mantieni nella parte superiore dello schermo. Per utilizzare Toolbar
nel frammento, fornisci un ID e ottieni un riferimento nel frammento, come con qualsiasi altra vista. Puoi anche valutare la possibilità di animare la barra degli strumenti utilizzando i comportamenti di CoordinatorLayout
.
<androidx.appcompat.widget.Toolbar
android:id="@+id/myToolbar"
... />
Se utilizzi una barra delle app di proprietà di frammenti, Google consiglia di usare direttamente le API Toolbar
. Non utilizzare setSupportActionBar()
e le API menu Fragment
, che sono appropriate solo per le barre delle app di proprietà delle attività.
Amplia il menu
Il metodo di praticità Toolbar
inflateMenu(int)
prende l'ID di una
risorsa del menu come parametro. Per gonfiare una risorsa del menu XML nella barra degli strumenti, passa resId
a questo metodo, come mostrato nell'esempio seguente:
Kotlin
class ExampleFragment : Fragment() { ... override fun onViewCreated(view: View, savedInstanceState: Bundle?) { ... viewBinding.myToolbar.inflateMenu(R.menu.sample_menu) } }
Java
public class ExampleFragment extends Fragment { ... @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { ... viewBinding.myToolbar.inflateMenu(R.menu.sample_menu); } }
Per gonfiare un'altra risorsa del menu XML, chiama di nuovo il metodo con resId
del nuovo menu. Le nuove voci vengono aggiunte al menu e le voci esistenti non vengono modificate né rimosse.
Se vuoi sostituire il set di menu esistente, cancella il menu prima di chiamare inflateMenu(int)
con il nuovo ID menu, come illustrato nell'esempio seguente:
Kotlin
class ExampleFragment : Fragment() { ... fun clearToolbarMenu() { viewBinding.myToolbar.menu.clear() } }
Java
public class ExampleFragment extends Fragment { ... public void clearToolbarMenu() { viewBinding.myToolbar.getMenu().clear() } }
Gestire gli eventi di clic
Puoi passare una
OnMenuItemClickListener
direttamente alla barra degli strumenti con il
metodo setOnMenuItemClickListener()
. Questo listener viene richiamato quando l'utente seleziona una voce di menu dai pulsanti di azione presentati alla fine della barra degli strumenti o dall'overflow associato. Il valore MenuItem
selezionato viene passato al metodo onMenuItemClick()
del listener e può essere utilizzato per utilizzare l'azione, come mostrato nell'esempio seguente:
Kotlin
class ExampleFragment : Fragment() { ... override fun onViewCreated(view: View, savedInstanceState: Bundle?) { ... viewBinding.myToolbar.setOnMenuItemClickListener { when (it.itemId) { R.id.action_settings -> { // Navigate to settings screen. true } R.id.action_done -> { // Save profile changes. true } else -> false } } } }
Java
public class ExampleFragment extends Fragment { ... @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { ... viewBinding.myToolbar.setOnMenuItemClickListener(item -> { switch (item.getItemId()) { case R.id.action_settings: // Navigate to settings screen. return true; case R.id.action_done: // Save profile changes. return true; default: return false; } }); } }
Modificare in modo dinamico il menu
Se la barra dell'app è di proprietà del frammento, puoi modificare Toolbar
in fase di runtime esattamente come qualsiasi altra vista.
Continuando con l'esempio precedente, l'opzione di menu Salva dovrebbe essere invisibile fino a quando l'utente non inizia la modifica e dovrebbe scomparire di nuovo quando l'ha toccata:
Kotlin
class ExampleFragment : Fragment() { ... fun updateToolbar() { isEditing = !isEditing val saveItem = viewBinding.myToolbar.menu.findItem(R.id.action_done) saveItem.isVisible = isEditing } }
Java
public class ExampleFragment extends Fragment { ... public void updateToolbar() { isEditing = !isEditing; MenuItem saveItem = viewBinding.myToolbar.getMenu().findItem(R.id.action_done); saveItem.setVisible(isEditing); } }
Aggiungi un'icona di navigazione
Se presente, il pulsante di navigazione viene visualizzato all'inizio della barra degli strumenti.
Se imposti un'icona di navigazione sulla barra degli strumenti, questa diventa visibile. Puoi anche impostare un elemento onClickListener()
specifico per la navigazione che viene chiamato ogni volta che l'utente fa clic sul pulsante di navigazione, come mostrato nell'esempio seguente:
Kotlin
class ExampleFragment : Fragment() { ... override fun onViewCreated(view: View, savedInstanceState: Bundle?) { ... myToolbar.setNavigationIcon(R.drawable.ic_back) myToolbar.setNavigationOnClickListener { view -> // Navigate somewhere. } } }
Java
public class ExampleFragment extends Fragment { ... @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { ... viewBinding.myToolbar.setNavigationIcon(R.drawable.ic_back); viewBinding.myToolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // Navigate somewhere. } }); } }