Utilizzo di AppBar

La barra delle app in alto fornisce un punto coerente lungo la parte superiore della finestra dell'app per la visualizzazione informazioni e azioni della schermata corrente.

Esempio di barra delle app in alto
Figura 1. Un esempio di barra delle app in alto.

La proprietà della barra delle app varia in base alle esigenze dell'app. Quando utilizzando frammenti, la barra delle app può essere implementata come ActionBar di proprietà dall'attività host o da una barra degli strumenti nel layout del frammento.

Se tutti gli schermi utilizzano la stessa barra delle app che si trova sempre in alto estende la larghezza dello schermo, usa un modello fornito dal tema, barra delle azioni ospitata dall'attività. L'utilizzo delle barre delle app a tema permette di mantenere dall'aspetto coerente e fornire uno spazio per ospitare menu di opzioni e Pulsante Su.

Utilizza una barra degli strumenti ospitata dal frammento se vuoi avere un maggiore controllo le dimensioni, il posizionamento e l'animazione della barra delle app su più schermate. Ad esempio, potresti aver bisogno di una barra delle app comprimibile o di una non occupa solo metà della larghezza dello schermo ed è centrato verticalmente.

Situazioni diverse richiedono approcci diversi, come il gonfiaggio i menu e rispondere all'interazione dell'utente. Comprendere le diverse e impiegare il migliore per la tua app ti fa risparmiare tempo e per assicurarti che l'app funzioni correttamente.

Gli esempi in questo argomento fanno riferimento a un ExampleFragment che contiene un profilo modificabile. Il frammento gonfia quanto segue Menu definito da XML nella barra delle 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 delle app di proprietà delle attività

La barra delle app è di solito di proprietà dell'attività di organizzatore. Quando l'app barra è di proprietà di un'attività, i frammenti possono interagire con la barra delle app eseguendo l'override dei metodi del framework richiamati durante la creazione dei frammenti.

Registrati con l'attività

Devi comunicare al sistema che il frammento della barra dell'app è presente nel popolamento del menu opzioni. A questo scopo, chiama setHasOptionsMenu(true) nel metodo onCreate(Bundle) del frammento, come mostrato di seguito esempio:

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 al menu. Quando un evento legato al menu si verifica un evento, come un clic, il metodo di gestione eventi è chiamato per la prima volta sull'attività prima di essere chiamato sul frammento.

Tuttavia, non fare affidamento su questo ordine nella logica dell'applicazione. Se lo stesso l'attività ospita più frammenti, ogni frammento può fornire menu opzioni, nel qual caso l'ordine di callback dipende dall'ordine in a cui vengono aggiunti i frammenti.

Amplia il menu

Per unire il menu al menu opzioni della barra delle app, sostituisci onCreateOptionsMenu() nel tuo frammento. Questo metodo riceve il menu della barra delle app corrente e un MenuInflater come parametri. Utilizza le funzionalità di strumento di riempimento del menu per creare un'istanza del menu del frammento, uniscile al menu corrente, come illustrato 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.

il menu opzioni ora contiene la parte del menu
Figura 2. Il menu opzioni ora contiene il tuo menu .

Gestire gli eventi di clic

Ogni attività e frammento che partecipa al menu opzioni possono rispondi al tocco. Il frammento onOptionsItemSelected() riceve la voce di menu selezionata come parametro e restituisce un valore booleano per indicare se il tocco viene consumato. Una volta l'attività o il frammento restituisce true da onOptionsItemSelected(), no gli altri frammenti partecipanti ricevono il callback.

Nella tua implementazione di onOptionsItemSelected(), utilizza un switch sul itemId della voce di menu. Se l'elemento selezionato è tuo, gestisci il tocco in modo appropriato e restituisce true per indicare in cui viene gestito l'evento di clic. Se l'elemento selezionato non è tua, chiama l'implementazione super. Per impostazione predefinita, super l'implementazione restituisce false per consentire 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

Posiziona la logica per nascondere o mostrare un pulsante o modificare l'icona in onPrepareOptionsMenu() Questo metodo viene chiamato subito prima della visualizzazione del menu.

Continuando con l'esempio precedente, il pulsante Salva dovrebbe essere invisibile finché l'utente non inizia ad apportare modifiche e dovrebbe scomparire dopo dall'utente. L'aggiunta di questa logica a onPrepareOptionsMenu() rende il menu presenta 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 tasto Pulsante Modifica per modificare le informazioni del profilo e la chiamata invalidateOptionsMenu(): sull'attività dell'host per richiedere che il sistema effettui una chiamata a onCreateOptionsMenu(). Dopo l'annullamento della convalida, puoi apportare gli aggiornamenti in onCreateOptionsMenu(). Una volta il menu si gonfia, il sistema chiama onPrepareOptionsMenu() e si 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 delle app di proprietà di un frammento

Se per la maggior parte delle schermate dell'app non è necessaria una barra delle app o se schermo richiede una barra delle app diversa dalle altre, puoi aggiungere una Toolbar al tuo con il layout a frammento. Anche se puoi aggiungere un Toolbar in qualsiasi punto del tuo la gerarchia di visualizzazione dei frammenti, in genere la si trova all'inizio della sullo schermo. Per utilizzare Toolbar nel frammento, fornisci un ID e ottenere un riferimento nel frammento, come con qualsiasi altro vista. Puoi anche animare la barra degli strumenti utilizzando CoordinatorLayout i comportamenti dei modelli,

<androidx.appcompat.widget.Toolbar
    android:id="@+id/myToolbar"
    ... />

Se utilizzi una barra delle app di proprietà di frammenti, Google consiglia di utilizzare la classe Toolbar direttamente le API. Non utilizzare setSupportActionBar(): e le API del menu Fragment, che sono appropriate solo per le barre delle app di proprietà delle attività.

Amplia il menu

Il metodo di convenienza ToolbarinflateMenu(int) prende l'ID di un risorsa di menu come parametro. Per gonfiare una risorsa di menu XML barra degli strumenti, passa resId a questo metodo, come mostrato di seguito esempio:

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 aumentare in modo artificioso un'altra risorsa di menu XML, richiama di nuovo il metodo con resId del nuovo menu. Le nuove voci di menu vengono aggiunte al menu e le voci di menu esistenti non vengono modificate né rimosse.

Se vuoi sostituire il set di menu esistente, cancella il menu prima chiamata inflateMenu(int) con il nuovo ID menu, come mostrato di seguito esempio:

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 trasmettere un OnMenuItemClickListener direttamente sulla barra degli strumenti utilizzando 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 overflow associato. L'elemento selezionato MenuItem viene passato al onMenuItemClick() e può essere utilizzato per consumare l'azione, come mostrato di seguito esempio:

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 il frammento è proprietario della barra delle app, puoi modificare Toolbar all'indirizzo un runtime simile a quello di qualsiasi altra vista.

Continuando con l'esempio precedente, l'opzione di menu Salva dovrebbe essere invisibile finché l'utente non inizia a modificarlo e dovrebbe scomparire di nuovo quando tocchi:

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

}

Se presente, il pulsante di navigazione viene visualizzato all'inizio della barra degli strumenti. Impostando un'icona di navigazione sulla barra degli strumenti, questa viene resa visibile. Puoi anche imposta un onClickListener() specifico per la navigazione che venga chiamato ogni volta l'utente fa clic sul pulsante di navigazione, come illustrato di seguito esempio:

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