Praca z paskiem aplikacji

górny pasek aplikacji zapewnia spójne miejsce u góry okna aplikacji, w którym wyświetlają się informacje i działania z bieżącego ekranu.

przykładowy pasek aplikacji
Rysunek 1. Przykładowy pasek aplikacji na górze.

Własność paska aplikacji różni się w zależności od potrzeb aplikacji. Gdy używasz fragmentów, pasek aplikacji można zaimplementować jako ActionBar, który należy do aktywności hosta lub paska narzędzi w układzie fragmentu.

Jeśli wszystkie ekrany mają ten sam pasek aplikacji, który znajduje się zawsze u góry ekranu i rozciąga się na szerokość ekranu, użyj paska działań hostowanego przez aktywność. Użycie pasków w aplikacjach z motywami pomaga uzyskać spójny wygląd i zapewnia miejsce na menu opcji oraz przycisk W górę.

Jeśli chcesz mieć większą kontrolę nad rozmiarem, położeniem i animacją paska aplikacji na wielu ekranach, użyj paska narzędzi hostowanego przez fragment. Może to być np. zwijający się pasek aplikacji lub taki, który rozciąga się tylko na połowę szerokości ekranu i jest wyśrodkowany w pionie.

Różne sytuacje wymagają odmiennego podejścia do takich kwestii jak nadmuchiwanie menu czy reagowanie na interakcje użytkowników. Zrozumienie różnych metod i wybranie tej, która najlepiej sprawdzi się w Twojej aplikacji, pozwoli Ci zaoszczędzić czas i zapewni jej prawidłowe działanie.

Przykłady w tym temacie odnoszą się do obiektu ExampleFragment zawierającego profil z możliwością edytowania. Ten fragment rozszerza to menu zdefiniowane w formacie XML na pasku aplikacji:

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

Menu zawiera dwie opcje: jedna do przejścia na ekran profilu i druga do zapisania wprowadzonych zmian w profilu.

Pasek aplikacji należących do aktywności

Pasek aplikacji należy najczęściej do aktywności gospodarza. Gdy pasek aplikacji należy do aktywności, fragmenty mogą wchodzić w interakcję z paskiem aplikacji, zastępując metody platformy wywoływane podczas tworzenia fragmentu.

Zarejestruj się w aktywności

Musisz poinformować system, że fragment paska aplikacji jest częścią menu opcji. Aby to zrobić, wywołaj setHasOptionsMenu(true) w metodzie onCreate(Bundle) fragmentu, jak w tym przykładzie:

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

Funkcja setHasOptionsMenu(true) informuje system, że fragment chce otrzymywać wywołania zwrotne związane z menu. Gdy wystąpi zdarzenie związane z menu, np. kliknięcie, metoda obsługi zdarzeń jest najpierw wywoływana dla działania, a następnie wywołana dla fragmentu.

Nie polegaj jednak na tej kolejności w logice aplikacji. Jeśli ta sama czynność obsługuje wiele fragmentów, każdy fragment może dostarczać opcje menu. W takim przypadku kolejność wywołania zwrotnego zależy od kolejności dodania fragmentów.

Rozszerz menu

Aby scalić menu z menu opcji na pasku aplikacji, zastąp onCreateOptionsMenu() we fragmencie. Ta metoda odbiera bieżące menu na pasku aplikacji i parametr MenuInflater. Użyj kreatora menu, aby utworzyć wystąpienie menu fragmentu, a następnie scal je z bieżącym menu, jak pokazano w poniższym przykładzie:

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

Rysunek 2 przedstawia zaktualizowane menu.

menu opcji zawiera teraz jego fragment
Rysunek 2. Menu opcji zawiera teraz jego fragment.

Obsługa zdarzeń kliknięcia

Każda aktywność i fragment, który występuje w menu opcji, może reagować na dotknięcia. Parametr onOptionsItemSelected() fragmentu odbiera wybrany element menu jako parametr i zwraca wartość logiczną wskazującą, czy kliknięcie zostało użyte. Gdy aktywność lub fragment zwróci wartość true z metody onOptionsItemSelected(), żaden inny fragment biorący udział w tym działaniu nie otrzyma wywołania zwrotnego.

W implementacji funkcji onOptionsItemSelected() użyj instrukcji switch w elemencie itemId elementu menu. Jeśli wybrany element należy do Ciebie, postępuj zgodnie z instrukcjami i zwracaj wartość true, aby wskazać, że zdarzenie kliknięcia jest obsługiwane. Jeśli wybrany element nie należy do Ciebie, wywołaj implementację super. Domyślnie implementacja super zwraca wartość false, aby umożliwić kontynuowanie przetwarzania 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);
        }

    }

}

Dynamiczne modyfikowanie menu

Umieść przycisk logiczny, aby ukryć lub wyświetlić przycisk bądź zmienić ikonę w elemencie onPrepareOptionsMenu(). Ta metoda jest wywoływana tuż przed wyświetleniem menu.

Podobnie jak w poprzednim przykładzie, przycisk Zapisz powinien być niewidoczny, dopóki użytkownik nie rozpocznie edycji, i powinien zniknąć po jego zapisaniu. Dodanie tego kodu do funkcji onPrepareOptionsMenu() sprawia, że menu wyświetla się prawidłowo:

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

Jeśli chcesz zaktualizować menu, na przykład gdy użytkownik kliknie przycisk Edytuj, aby edytować informacje w profilu, wywołaj invalidateOptionsMenu() w aktywności hosta, aby poprosić system o wywołanie onCreateOptionsMenu(). Po unieważnieniu danych możesz wprowadzić zmiany w narzędziu onCreateOptionsMenu(). Po powiększeniu menu system wywołuje funkcję onPrepareOptionsMenu() i aktualizuje menu, aby odzwierciedlić bieżący stan fragmentu.

Kotlin

class ExampleFragment : Fragment() {
    ...
    fun updateOptionsMenu() {
        isEditing = !isEditing
        requireActivity().invalidateOptionsMenu()
    }
}

Java

public class ExampleFragment extends Fragment {
    ...
    public void updateOptionsMenu() {
        isEditing = !isEditing;
        requireActivity().invalidateOptionsMenu();
    }
}

Pasek aplikacji należący do fragmentu

Jeśli większość ekranów w aplikacji nie potrzebuje paska aplikacji lub jeśli jeden z nich wymaga innego paska aplikacji niż pozostałe, do układu fragmentów możesz dodać Toolbar. Chociaż możesz dodać Toolbar w dowolnym miejscu hierarchii widoku fragmentu, zasadniczo musisz go umieścić na górze ekranu. Aby użyć we fragmencie Toolbar, podaj identyfikator i uzyskaj odniesienie do niego we fragmencie, tak jak w przypadku każdego innego widoku. Możesz też animować pasek narzędzi za pomocą zachowań CoordinatorLayout.

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

W przypadku korzystania z paska aplikacji należącego do fragmentu zalecamy bezpośrednie korzystanie z interfejsów API Toolbar. Nie używaj interfejsów API setSupportActionBar() ani menu Fragment, które są odpowiednie tylko w przypadku pasków aplikacji należących do aktywności.

Rozszerz menu

Metoda zapewniająca wygodę inflateMenu(int) Toolbar przyjmuje jako parametr identyfikator zasobu menu. Aby powiększyć zasób menu XML na pasku narzędzi, przekaż metodę resId do tej metody, jak w tym przykładzie:

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

}

Aby powiększyć inny zasób menu XML, wywołaj tę metodę ponownie za pomocą polecenia resId w nowym menu. Do menu zostaną dodane nowe pozycje, a istniejące pozycje nie zostaną zmodyfikowane ani usunięte.

Jeśli chcesz zastąpić obecny zestaw menu, wyczyść menu, zanim wywołasz funkcję inflateMenu(int) nowym identyfikatorem menu, jak w tym przykładzie:

Kotlin

class ExampleFragment : Fragment() {
    ...
    fun clearToolbarMenu() {
        viewBinding.myToolbar.menu.clear()
    }
}

Java

public class ExampleFragment extends Fragment {
    ...
    public void clearToolbarMenu() {

        viewBinding.myToolbar.getMenu().clear()

    }

}

Obsługa zdarzeń kliknięcia

Możesz przekazać OnMenuItemClickListener bezpośrednio do paska narzędzi za pomocą metody setOnMenuItemClickListener(). Ten detektor jest wywoływany, gdy użytkownik wybierze element menu za pomocą przycisków poleceń znajdujących się na końcu paska narzędzi lub powiązanego menu. Wybrany parametr MenuItem jest przekazywany do metody onMenuItemClick() detektora i może służyć do wykonywania działania, jak widać w tym przykładzie:

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

Dynamiczne modyfikowanie menu

Gdy fragment jest właścicielem paska aplikacji, możesz modyfikować Toolbar w czasie działania tak samo jak każdy inny widok.

Kontynuując poprzedni przykład, opcja menu Zapisz powinna być niewidoczna do czasu rozpoczęcia edycji przez użytkownika i powinna zniknąć po kliknięciu:

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

}

Jeśli ten przycisk jest widoczny, na początku paska narzędzi pojawi się przycisk nawigacyjny. Ustawienie ikony nawigacji na pasku narzędzi sprawia, że jest ona widoczna. Możesz też ustawić element onClickListener() związany z nawigacją, który jest wywoływany za każdym razem, gdy użytkownik kliknie przycisk nawigacyjny, jak w tym przykładzie:

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