Łączenie komponentów interfejsu z kontrolerem NavController za pomocą interfejsu NavigationUI

Komponent Nawigacja zawiera klasę NavigationUI. Ta klasa zawiera metody statyczne, które zarządzają nawigacją za pomocą górnego paska aplikacji, panelu nawigacyjnego i dolnej części nawigacji.

Górny pasek aplikacji

Pasek aplikacji u góry zapewnia spójne miejsce u góry aplikacji do wyświetlania informacji i czynności z bieżącego ekranu.

Ekran z paskiem aplikacji u góry
Rysunek 1. Ekran z paskiem aplikacji u góry.

NavigationUI zawiera metody, które automatycznie aktualizują zawartość górnego paska aplikacji, gdy użytkownicy poruszają się po aplikacji. Na przykład NavigationUI używa etykiet miejsc docelowych z grafu nawigacyjnego, aby utrzymywać aktualny tytuł górnego paska aplikacji.

<navigation>
    <fragment ...
              android:label="Page title">
      ...
    </fragment>
</navigation>

Jeśli używasz NavigationUI w ramach implementacji górnego paska aplikacji opisanej poniżej, etykieta dołączona do miejsc docelowych może być automatycznie wypełniana na podstawie argumentów przekazanych do miejsca docelowego za pomocą formatu {argName} w etykiecie.

NavigationUI obsługuje te typy paska aplikacji u góry:

Więcej informacji o paskach aplikacji znajdziesz w artykule Konfigurowanie paska aplikacji.

AppBarConfiguration

NavigationUI używa obiektu AppBarConfiguration do zarządzania działaniem przycisku nawigacji w lewym górnym rogu obszaru wyświetlania aplikacji. Sposób działania przycisku nawigacji zmienia się w zależności od tego, czy użytkownik znajduje się na miejscu docelowym najwyższego poziomu.

Miejsce docelowe najwyższego poziomu to miejsce docelowe katalogu głównego lub najwyższego poziomu w zbiorze miejsc docelowych powiązanych hierarchicznie. Na pasku aplikacji na górze nie wyświetla się przycisk W górę w przypadku miejsc docelowych najwyższego poziomu, ponieważ nie ma miejsc docelowych wyższego poziomu. Domyślnie początkowy punkt docelowy aplikacji jest jedynym punktem docelowym najwyższego poziomu.

Gdy użytkownik znajduje się na miejscu docelowym najwyższego poziomu, przycisk Nawigacja zmienia się w ikonę szuflady, jeśli miejsce docelowe korzysta z elementu DrawerLayout. Jeśli miejsce docelowe nie korzysta z DrawerLayout, przycisk Nawigacja jest ukryty. Gdy użytkownik znajduje się w dowolnym innym miejscu docelowym, przycisk nawigacji wyświetla się jako przycisk W górę . Aby skonfigurować przycisk nawigacji, używając jako miejsca docelowego na najwyższym poziomie tylko miejsca docelowego początkowego, utwórz obiekt AppBarConfiguration i przenieś do niego odpowiedni graf nawigacji, jak pokazano poniżej:

Kotlin

val appBarConfiguration = AppBarConfiguration(navController.graph)

Java

AppBarConfiguration appBarConfiguration =
        new AppBarConfiguration.Builder(navController.getGraph()).build();

W niektórych przypadkach zamiast domyślnego miejsca docelowego na początku może być konieczne zdefiniowanie kilku miejsc docelowych najwyższego poziomu. W takich przypadkach możesz użyć BottomNavigationView, aby mieć ekrany nadrzędne, które nie są ze sobą powiązane hierarchicznie i mogą mieć własne zestawy powiązanych miejsc docelowych. W takich przypadkach możesz zamiast tego przekazać konstruktorowi zestaw identyfikatorów docelowych, jak pokazano poniżej:

Kotlin

val appBarConfiguration = AppBarConfiguration(setOf(R.id.main, R.id.profile))

Java

AppBarConfiguration appBarConfiguration =
        new AppBarConfiguration.Builder(R.id.main, R.id.profile).build();

Tworzenie paska narzędzi

Aby utworzyć pasek narzędzi z NavigationUI, najpierw zdefiniuj go w głównej aktywności, jak pokazano poniżej:

<LinearLayout>
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar" />
    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        ... />
    ...
</LinearLayout>

Następnie wywołaj funkcję setupWithNavController() z metody onCreate() głównej aktywności, jak pokazano w tym przykładzie:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    setContentView(R.layout.activity_main)

    ...

    val navController = findNavController(R.id.nav_host_fragment)
    val appBarConfiguration = AppBarConfiguration(navController.graph)
    findViewById<Toolbar>(R.id.toolbar)
        .setupWithNavController(navController, appBarConfiguration)
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.activity_main);

    ...

    NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    AppBarConfiguration appBarConfiguration =
            new AppBarConfiguration.Builder(navController.getGraph()).build();
    Toolbar toolbar = findViewById(R.id.toolbar);
    NavigationUI.setupWithNavController(
            toolbar, navController, appBarConfiguration);
}

Aby skonfigurować przycisk nawigacji tak, aby był widoczny jako przycisk W górę dla wszystkich miejsc docelowych, podczas tworzenia AppBarConfiguration podaj pusty zestaw identyfikatorów miejsc docelowych najwyższego poziomu. Może to być przydatne, jeśli na przykład masz drugą aktywność, która powinna wyświetlać przycisk W górę we wszystkich miejscach docelowych Toolbar. Dzięki temu użytkownik może wrócić do aktywności nadrzędnej, gdy nie ma innych miejsc docelowych w łańcuchu. Możesz użyć parametru setFallbackOnNavigateUpListener(), aby określić zachowanie kreacji zastępczej w przypadku, gdy navigateUp() nie robi nic. Przykład:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    ...

    val navHostFragment =
        supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val navController = navHostFragment.navController
    val appBarConfiguration = AppBarConfiguration(
        topLevelDestinationIds = setOf(),
        fallbackOnNavigateUpListener = ::onSupportNavigateUp
    )
    findViewById<Toolbar>(R.id.toolbar)
        .setupWithNavController(navController, appBarConfiguration)
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...

    NavHostFragment navHostFragment = (NavHostFragment) supportFragmentManager.findFragmentById(R.id.nav_host_fragment);
    NavController navController = navHostFragment.getNavController();
    AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder()
        .setFallbackOnNavigateUpListener(::onSupportNavigateUp)
        .build();
    Toolbar toolbar = findViewById(R.id.toolbar);
    NavigationUI.setupWithNavController(
            toolbar, navController, appBarConfiguration);
}

Uwzględnij CollapsingToolbarLayout

Aby uwzględnić CollapsingToolbarLayout na pasku narzędzi, najpierw zdefiniuj układ paska narzędzi i otaczających go elementów w swojej aktywności, jak pokazano poniżej:

<LinearLayout>
    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/tall_toolbar_height">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleGravity="top"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"/>
        </com.google.android.material.appbar.CollapsingToolbarLayout>
    </com.google.android.material.appbar.AppBarLayout>

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        ... />
    ...
</LinearLayout>

Następnie wywołaj metodę onCreate głównej czynności (aktywacji) za pomocą metody setupWithNavController(), jak pokazano poniżej:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    setContentView(R.layout.activity_main)

    ...

    val layout = findViewById<CollapsingToolbarLayout>(R.id.collapsing_toolbar_layout)
    val toolbar = findViewById<Toolbar>(R.id.toolbar)
    val navHostFragment =
        supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val navController = navHostFragment.navController
    val appBarConfiguration = AppBarConfiguration(navController.graph)
    layout.setupWithNavController(toolbar, navController, appBarConfiguration)
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.activity_main);

    ...

    CollapsingToolbarLayout layout = findViewById(R.id.collapsing_toolbar_layout);
    Toolbar toolbar = findViewById(R.id.toolbar);
    NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment);
    NavController navController = navHostFragment.getNavController();
    AppBarConfiguration appBarConfiguration =
            new AppBarConfiguration.Builder(navController.getGraph()).build();
    NavigationUI.setupWithNavController(layout, toolbar, navController, appBarConfiguration);
}

Pasek działań

Aby dodać obsługę nawigacji do domyślnego paska czynności, wywołaj metodę setupActionBarWithNavController() z metody onCreate() głównej czynności, jak pokazano poniżej. Pamiętaj, że musisz zadeklarować AppBarConfiguration poza onCreate(), ponieważ używasz go również podczas zastępowania onSupportNavigateUp():

Kotlin

private lateinit var appBarConfiguration: AppBarConfiguration

...

override fun onCreate(savedInstanceState: Bundle?) {
    ...

    val navHostFragment =
        supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val navController = navHostFragment.navController
    appBarConfiguration = AppBarConfiguration(navController.graph)
    setupActionBarWithNavController(navController, appBarConfiguration)
}

Java

AppBarConfiguration appBarConfiguration;

...

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...

    NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment);
    NavController navController = navHostFragment.getNavController();
    appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
    NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
}

Następnie zastąpij onSupportNavigateUp(), aby obsłużyć nawigację w górę:

Kotlin

override fun onSupportNavigateUp(): Boolean {
    val navController = findNavController(R.id.nav_host_fragment)
    return navController.navigateUp(appBarConfiguration)
            || super.onSupportNavigateUp()
}

Java

@Override
public boolean onSupportNavigateUp() {
    NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    return NavigationUI.navigateUp(navController, appBarConfiguration)
            || super.onSupportNavigateUp();
}

Obsługa wariantów paska aplikacji

Dodanie do aktywności paska aplikacji na górze działa dobrze, gdy układ paska jest podobny w przypadku każdego miejsca docelowego w aplikacji. Jeśli jednak pasek aplikacji na górze zmienia się znacznie w zależności od miejsca docelowego, rozważ usunięcie go z aktywności i zamiast tego zdefiniowanie go w każdym fragmencie miejsca docelowego.

Na przykład jedno z miejsc docelowych może używać standardowego Toolbar, a drugie AppBarLayout do tworzenia bardziej złożonego paska aplikacji z kartami, jak pokazano na rysunku 2.

2 wariacje górnego paska aplikacji: standardowy pasek narzędzi po lewej stronie oraz układ z paskiem narzędzi i kartami po prawej stronie
Rysunek 2. Dwa warianty paska aplikacji. Po lewej stronie standardowa opcjaToolbar. Po prawej stronie widoczne są AppBarLayout z Toolbar i kartami.

Aby zaimplementować to rozwiązanie w fragmentach docelowych za pomocą elementu NavigationUI, najpierw zdefiniuj pasek aplikacji w każdym z ich układów, zaczynając od fragmentu docelowego, który używa standardowego paska narzędzi:

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

Następnie zdefiniuj fragment docelowy, który używa paska aplikacji z kartami:

<LinearLayout>
    <com.google.android.material.appbar.AppBarLayout
        ... />

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

        <com.google.android.material.tabs.TabLayout
            ... />

    </com.google.android.material.appbar.AppBarLayout>
    ...
</LinearLayout>

Logika konfiguracji nawigacji jest taka sama w przypadku obu tych fragmentów, z tym że wywołanie funkcji setupWithNavController() powinno nastąpić z metody onViewCreated() każdego fragmentu, a nie z metody aktywności:

Kotlin

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    val navController = findNavController()
    val appBarConfiguration = AppBarConfiguration(navController.graph)

    view.findViewById<Toolbar>(R.id.toolbar)
            .setupWithNavController(navController, appBarConfiguration)
}

Java

@Override
public void onViewCreated(@NonNull View view,
                          @Nullable Bundle savedInstanceState) {
    NavController navController = Navigation.findNavController(view);
    AppBarConfiguration appBarConfiguration =
            new AppBarConfiguration.Builder(navController.getGraph()).build();
    Toolbar toolbar = view.findViewById(R.id.toolbar);

    NavigationUI.setupWithNavController(
            toolbar, navController, appBarConfiguration);
}

Powiązanie miejsc docelowych z pozycjami menu

NavigationUI zawiera też pomocnicze funkcje do łączenia miejsc docelowych z interfejsami użytkownika opartymi na menu. NavigationUI zawiera metodę pomocniczą onNavDestinationSelected(), która przyjmuje MenuItem oraz NavController, które hostują powiązane miejsce docelowe. Jeśli id MenuItem pasuje do id miejsca docelowego, NavController może nawigować do tego miejsca.

Przykładowo fragmenty kodu XML poniżej definiują pozycję menu i miejsce docelowe z wspólnym elementem id, details_page_fragment:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    ... >

    ...

    <fragment android:id="@+id/details_page_fragment"
         android:label="@string/details"
         android:name="com.example.android.myapp.DetailsFragment" />
</navigation>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    ...

    <item
        android:id="@+id/details_page_fragment"
        android:icon="@drawable/ic_details"
        android:title="@string/details" />
</menu>

Jeśli menu zostało dodane za pomocą elementu onCreateOptionsMenu() w aktywności, możesz powiązać elementy menu z miejscami docelowymi, zastępując element onOptionsItemSelected() w aktywności elementem onNavDestinationSelected(), jak pokazano w tym przykładzie:

Kotlin

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    val navController = findNavController(R.id.nav_host_fragment)
    return item.onNavDestinationSelected(navController) || super.onOptionsItemSelected(item)
}

Java

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    return NavigationUI.onNavDestinationSelected(item, navController)
            || super.onOptionsItemSelected(item);
}

Gdy użytkownik kliknie element menu details_page_fragment, aplikacja automatycznie przejdzie do odpowiedniego miejsca docelowego z tym samym id.

Dodawanie panelu nawigacji

Panel nawigacyjny to panel interfejsu użytkownika, który zawiera główne menu nawigacyjne aplikacji. Szuflada pojawia się, gdy użytkownik dotknie ikony szuflady na pasku aplikacji lub przesunie palcem od lewej krawędzi ekranu.

otwarty panel nawigacji z menu nawigacji
Rysunek 3. Otwartą szufladę z menu nawigacyjnym.

Ikona szuflady jest wyświetlana we wszystkich miejscach docelowych najwyższego poziomu, które korzystają z DrawerLayout.

Aby dodać panel nawigacyjny, najpierw zadeklaruj widok DrawerLayout jako widok główny. W DrawerLayout dodaj układ głównej treści interfejsu użytkownika oraz inny widok zawierający zawartość panelu nawigacyjnego.

Na przykład ten układ używa elementu DrawerLayout z 2 widokami podrzędnymi: NavHostFragment zawierającym główną treść orazNavigationViewzawierającym zawartość szuflady nawigacyjnej.

<?xml version="1.0" encoding="utf-8"?>
<!-- Use DrawerLayout as root container for activity -->
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <!-- Layout to contain contents of main body of screen (drawer will slide over this) -->
    <androidx.fragment.app.FragmentContainerView
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:id="@+id/nav_host_fragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />

    <!-- Container for contents of drawer - use NavigationView to make configuration easier -->
    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true" />

</androidx.drawerlayout.widget.DrawerLayout>

Następnie połącz DrawerLayout z grafem nawigacji, przekazując go do AppBarConfiguration, jak pokazano w tym przykładzie:

Kotlin

val appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout)

Java

AppBarConfiguration appBarConfiguration =
        new AppBarConfiguration.Builder(navController.getGraph())
            .setDrawerLayout(drawerLayout)
            .build();

Następnie w klasie głównej aktywności wywołaj metodę onCreate()setupWithNavController(), jak pokazano poniżej:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    setContentView(R.layout.activity_main)

    ...

    val navHostFragment =
        supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val navController = navHostFragment.navController
    findViewById<NavigationView>(R.id.nav_view)
        .setupWithNavController(navController)
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.activity_main);

    ...

    NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment);
    NavController navController = navHostFragment.getNavController();
    NavigationView navView = findViewById(R.id.nav_view);
    NavigationUI.setupWithNavController(navView, navController);
}

Od wersji Nawigacja 2.4.0-alpha01 stan każdego elementu menu jest zapisywany i przywracany podczas korzystania z setupWithNavController.

Dolna nawigacja

NavigationUI może też obsługiwać nawigację u dołu ekranu. Gdy użytkownik wybierze element menu, funkcja NavController wywołuje funkcję onNavDestinationSelected() i automatycznie aktualizuje wybrany element na dolnym pasku nawigacji.

dolny pasek nawigacyjny
Rysunek 4. Dolny pasek nawigacyjny.

Aby utworzyć pasek dolnej nawigacji w aplikacji, najpierw zdefiniuj go w głównej aktywności, jak pokazano poniżej:

<LinearLayout>
    ...
    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        ... />
    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_nav"
        app:menu="@menu/menu_bottom_nav" />
</LinearLayout>

Następnie w klasie głównej aktywności wywołaj metodę onCreate()setupWithNavController(), jak pokazano poniżej:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    setContentView(R.layout.activity_main)

    ...

    val navHostFragment =
        supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
    val navController = navHostFragment.navController
    findViewById<BottomNavigationView>(R.id.bottom_nav)
        .setupWithNavController(navController)
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.activity_main);

    ...

    NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment);
    NavController navController = navHostFragment.getNavController();
    BottomNavigationView bottomNav = findViewById(R.id.bottom_nav);
    NavigationUI.setupWithNavController(bottomNav, navController);
}

Od wersji Nawigacja 2.4.0-alpha01 stan każdego elementu menu jest zapisywany i przywracany podczas korzystania z setupWithNavController.

Nasłuchiwanie zdarzeń nawigacji

Interakcja z NavController jest główną metodą nawigacji między miejscami docelowymi. NavControllerjest odpowiedzialny za zastąpienie zawartości NavHostnową lokalizacją docelową. W wielu przypadkach elementy interfejsu, takie jak górna część paska aplikacji lub inne trwałe elementy sterujące nawigacją, np. BottomNavigationBar, znajdują się poza NavHost i muszą być aktualizowane podczas przechodzenia między miejscami docelowymi.

NavController udostępnia interfejs OnDestinationChangedListener, który jest wywoływany, gdy bieżące miejsce docelowe funkcji NavController lub jej argumenty ulegną zmianie. Nowy słuchacz może zostać zarejestrowany za pomocą metody addOnDestinationChangedListener(). Pamiętaj, że jeśli podczas wywołania funkcji addOnDestinationChangedListener() istnieje bieżący cel, zostanie on natychmiast wysłany do słuchacza.

NavigationUI używa OnDestinationChangedListener, aby te typowe komponenty interfejsu były dostępne w menu nawigacji. Pamiętaj jednak, że możesz też użyć OnDestinationChangedListener samodzielnie, aby poinformować niestandardowe UI lub logikę biznesową o zdarzeniach nawigacyjnych.

Możesz na przykład mieć wspólne elementy interfejsu, które chcesz wyświetlać w niektórych obszarach aplikacji, a w innych ukrywać. Za pomocą własnej funkcji OnDestinationChangedListener możesz wyświetlać lub ukrywać te elementy interfejsu w zależności od miejsca docelowego, jak w tym przykładzie:

Kotlin

navController.addOnDestinationChangedListener { _, destination, _ ->
   if(destination.id == R.id.full_screen_destination) {
       toolbar.visibility = View.GONE
       bottomNavigationView.visibility = View.GONE
   } else {
       toolbar.visibility = View.VISIBLE
       bottomNavigationView.visibility = View.VISIBLE
   }
}

Java

navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
   @Override
   public void onDestinationChanged(@NonNull NavController controller,
           @NonNull NavDestination destination, @Nullable Bundle arguments) {
       if(destination.getId() == R.id.full_screen_destination) {
           toolbar.setVisibility(View.GONE);
           bottomNavigationView.setVisibility(View.GONE);
       } else {
           toolbar.setVisibility(View.VISIBLE);
           bottomNavigationView.setVisibility(View.VISIBLE);
       }
   }
});

Słuchacze na podstawie argumentów

Możesz też użyć w grafie nawigacji argumentów z wartościami domyślnymi, których odpowiedni kontroler interfejsu użytkownika może używać do aktualizowania stanu. Zamiast opierać logikę w funkcji OnDestinationChangedListener na identyfikatorze miejsca docelowego, jak w poprzednim przykładzie, możesz utworzyć argument w funkcji NavGraph:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/navigation\_graph"
    app:startDestination="@id/fragmentOne">
    <fragment
        android:id="@+id/fragmentOne"
        android:name="com.example.android.navigation.FragmentOne"
        android:label="FragmentOne">
        <action
            android:id="@+id/action\_fragmentOne\_to\_fragmentTwo"
            app:destination="@id/fragmentTwo" />
    </fragment>
    <fragment
        android:id="@+id/fragmentTwo"
        android:name="com.example.android.navigation.FragmentTwo"
        android:label="FragmentTwo">
        <argument
            android:name="ShowAppBar"
            android:defaultValue="true" />
    </fragment>
</navigation>

Ten argument nie jest używany podczas przechodzenia do miejsca docelowego, ale jako sposób dołączania dodatkowych informacji do miejsca docelowego za pomocą defaultValue. W tym przypadku wartość wskazuje, czy pasek aplikacji powinien być wyświetlany na tej stronie docelowej.

Możemy teraz dodać OnDestinationChangedListener w sekcji Activity:

Kotlin

navController.addOnDestinationChangedListener { _, _, arguments ->
    appBar.isVisible = arguments?.getBoolean("ShowAppBar", false) == true
}

Java

navController.addOnDestinationChangedListener(
        new NavController.OnDestinationChangedListener() {
            @Override
            public void onDestinationChanged(
                    @NonNull NavController controller,
                    @NonNull NavDestination destination,
                    @Nullable Bundle arguments
            ) {
                boolean showAppBar = false;
                if (arguments != null) {
                    showAppBar = arguments.getBoolean("ShowAppBar", false);
                }
                if(showAppBar) {
                    appBar.setVisibility(View.VISIBLE);
                } else {
                    appBar.setVisibility(View.GONE);
                }
            }
        }
);

NavController wywołuje to wywołanie zwrotne, gdy zmienia się miejsce docelowe nawigacji. Obiekt Activity może teraz aktualizować stan lub widoczność należących do niego komponentów UI na podstawie argumentów otrzymanych w wywołaniu zwrotnym.

Jedną z zalet tego podejścia jest to, że Activity widzi tylko argumenty w grafie nawigacji i nie zna ról ani obowiązków poszczególnych Fragment. Podobnie poszczególne fragmenty nie wiedzą o zawierającym Activity ani o elementach interfejsu użytkownika, do których należą.

Dodatkowe materiały

Więcej informacji o nawigacji znajdziesz w tych dodatkowych materiałach.

Próbki

Ćwiczenia z programowania

Posty na blogu

Filmy