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

Komponent Nawigacja zawiera NavigationUI zajęcia. Ta klasa zawiera metody statyczne, które zarządzają nawigacją na górze pasek aplikacji, panel nawigacji i dolna nawigacja.

Górny pasek aplikacji

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

ekran z górnym paskiem aplikacji
Rysunek 1. Ekran z wyświetlonym górnym paskiem aplikacji.

NavigationUI zawiera metody, które automatycznie aktualizują treść u góry strony na pasku aplikacji, gdy użytkownicy poruszają się po aplikacji. Na przykład NavigationUI używa parametru etykiety miejsc docelowych z wykresu nawigacyjnego, by zachować tytuł najpopularniejszej aplikacji jest aktualny.

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

Jeśli używasz interfejsu NavigationUI z najważniejszymi implementacjami paska aplikacji omówionymi poniżej, etykieta dołączona do miejsc docelowych może być automatycznie wypełniana z pola argumentów miejsca docelowego w formacie {argName} w .

NavigationUI zapewnia obsługę tych najpopularniejszych typów pasków aplikacji:

Więcej informacji na temat pasków aplikacji znajdziesz w artykule Konfigurowanie paska aplikacji.

Konfiguracja paska AppBar

NavigationUI używa: AppBarConfiguration umożliwia zarządzanie zachowaniem przycisku nawigacji w lewym górnym rogu obszaru wyświetlania aplikacji. Działanie przycisku nawigacyjnego zmienia się w zależności od czy użytkownik znajduje się w miejscu docelowym najwyższego poziomu.

Miejsce docelowe najwyższego poziomu to miejsce docelowe najwyższego poziomu, czyli miejsce docelowe najwyższego poziomu w zbiorze hierarchicznie powiązane miejsca docelowe. Miejsca docelowe najwyższego poziomu nie mają Przycisk w górę na górnym pasku aplikacji, ponieważ nie ma miejsca docelowego wyższego poziomu. Według domyślnie miejsce docelowe początkowe jest jedynym miejscem docelowym najwyższego poziomu.

Gdy użytkownik znajduje się w miejscu docelowym najwyższego poziomu, przycisk nawigacyjny staje się ikona panelu jeśli miejsce docelowe używa DrawerLayout. Jeśli miejsce docelowe nie używa tagu DrawerLayout, przycisk nawigacyjny jest ukryty. Gdy użytkownik znajduje się w jakimkolwiek innym miejscu docelowym, przycisk nawigacji wyświetla się jako przycisk W górę. Aby skonfigurować przycisk Nawigacja, używając tylko miejsca docelowego jako miejsca docelowego miejsce docelowe najwyższego poziomu, utwórz obiekt AppBarConfiguration i przekaż odpowiedni wykres nawigacyjny w następujący sposób:

Kotlin

val appBarConfiguration = AppBarConfiguration(navController.graph)

Java

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

W niektórych przypadkach może zajść potrzeba zdefiniowania wielu miejsc docelowych najwyższego poziomu użycia domyślnego miejsca docelowego. Korzystanie z BottomNavigationView w przypadku takiej sytuacji, gdy są równorzędne ekrany, które nie są są ze sobą powiązane hierarchicznie i mogą mieć swój własny zestaw miejsca docelowe. W takich przypadkach możesz zamiast tego przekazać zestaw miejsc docelowych Identyfikatory konstruktora, 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();

Utwórz pasek narzędzi

Aby utworzyć pasek narzędzi z dodatkiem NavigationUI, najpierw zdefiniuj pasek w głównym aktywność, która wygląda tak:

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

Następnie zadzwoń pod numer setupWithNavController() za pomocą metody onCreate() Twojej głównej aktywności, jak pokazano w tym przykładzie przykład:

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ć dla wszystkich przycisk nawigacji jako przycisk W górę miejsca docelowe, prześlij pusty zestaw identyfikatorów miejsc docelowych dla najwyższego poziomu miejsca docelowe podczas tworzenia AppBarConfiguration. To może być przydatne jeśli na przykład masz drugie działanie, które powinno wyświetlać przycisk W górę w: Toolbar we wszystkich miejscach docelowych. Dzięki temu użytkownik będzie mógł wrócić do aktywności rodzica, gdy z tyłu nie ma innych miejsc docelowych stosów. Za pomocą setFallbackOnNavigateUpListener() aby kontrolować działanie kreacji zastępczej, gdy navigateUp() nic nie rób, jak widać w tym przykładzie:

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 układ paska narzędzi zwijania

Aby dodać CollapsingToolbarLayout do paska narzędzi, najpierw zdefiniuj Pasek narzędzi i układ otoczenia w Twojej aktywności, tak jak 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 zadzwoń pod numer setupWithNavController() za pomocą metody onCreate Twojej głównej aktywności, jak 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ć pomoc nawigacyjną do domyślnego paska działań, wywołaj setupActionBarWithNavController() za pomocą metody onCreate() Twojej głównej aktywności, jak pokazano poniżej. Pamiętaj, że musisz zadeklarować AppBarConfiguration poza onCreate(), ponieważ użyj go także do zastępowania parametru 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ąp onSupportNavigateUp(), aby obsługiwać nawigację do góry:

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 odmian paska aplikacji

Dodanie górnego paska aplikacji do aktywności działa dobrze, gdy jest włączony układ paska aplikacji. w przypadku każdego miejsca docelowego w aplikacji. Jeśli jednak górny pasek aplikacji się zmieni w wielu miejscach docelowych, rozważ usunięcie górnego paska aplikacji Twojej aktywności i definiując ją w każdym docelowym fragmencie.

Na przykład w jednym z Twoich miejsc docelowych możesz używać standardowego Toolbar, a inny używa AppBarLayout do utworzenia bardziej złożonego paska aplikacji z kartami, jak co pokazano na rys. 2.

2 najpopularniejsze odmiany paska aplikacji, standardowy pasek narzędzi po lewej stronie,
            aplikacja z paskiem narzędzi i kartami po prawej stronie
Rysunek 2. Dwie odmiany paska aplikacji. Po lewej stronie Toolbar Po prawej stronie znajduje się AppBarLayout ze znakiem Toolbar i karty.

Aby zaimplementować ten przykład we fragmentach docelowych za pomocą NavigationUI, najpierw zdefiniuj pasek aplikacji w każdym z układów fragmentów, zaczyna się od fragmentu docelowego ze standardowym paskiem narzędzi:

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

Następnie zdefiniuj fragment docelowy, który korzysta z 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 w obu tych fragmentach taka sama, z tym wyjątkiem, że należy zadzwonić setupWithNavController() z metody onViewCreated() każdego fragmentu, zamiast inicjować z 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ąż miejsca docelowe z pozycjami menu

NavigationUI udostępnia również pomocniki w łączeniu miejsc docelowych z interfejsem opartym na menu NavigationUI zawiera metodę pomocniczą, onNavDestinationSelected(), , który obejmuje MenuItem razem z NavController hostujący powiązane miejsce docelowe. Jeśli id w MenuItem jest zgodny z id miejsce docelowe, NavController może przejść do tego miejsca docelowego.

Przykładowo poniższe fragmenty kodu XML definiują pozycję menu i miejsce docelowe ze typowy 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 Twoje menu zostało dodane za pomocą sekcji onCreateOptionsMenu() aktywności, na przykład: możesz powiązać pozycje menu z miejscami docelowymi, zastępując atrybut Aktywność onOptionsItemSelected(), aby zadzwonić do: onNavDestinationSelected(), tak jak w: następujący przykład:

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

Teraz, gdy użytkownik kliknie pozycję w menu details_page_fragment, aplikacja automatycznie przechodzi do odpowiedniego miejsca docelowego z tym samym ustawieniem id.

Dodaj panel nawigacji

Panel nawigacji to panel interfejsu, w którym widać główne menu nawigacyjne aplikacji. Panel pojawia się, gdy użytkownik dotknie jego ikony na pasku aplikacji lub gdy użytkownik przesunie palcem od lewej krawędzi ekranu.

otwarta szuflada z menu nawigacyjnym
Rysunek 3. Otwarta szuflada wyświetlająca elementy nawigacyjne

Ikona panelu jest wyświetlana na miejsca docelowe najwyższego poziomu, w których jest używany DrawerLayout.

Aby dodać panel nawigacji, najpierw zadeklaruj DrawerLayout jako poziom główny widok. W DrawerLayout dodaj układ głównej zawartości interfejsu. inny widok z zawartością panelu nawigacji.

Na przykład ten układ korzysta z elementu DrawerLayout z 2 widokami podrzędnymi: NavHostFragment na które zawierają główną treść, NavigationView i sprawdź zawartość panelu nawigacji.

<?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 podłącz urządzenie DrawerLayout do wykresu nawigacyjnego, przekazując go do funkcji AppBarConfiguration, jak widać na wykresie następujący przykład:

Kotlin

val appBarConfiguration = AppBarConfiguration(navController.graph, drawerLayout)

Java

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

Następnie w ramach głównych zajęć wybierz wywołanie setupWithNavController() za pomocą metody onCreate() Twojej głównej aktywności, jak 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);
}

Zaczyna się za Nawigacja 2.4.0-alfa01, stan każdego elementu menu zostanie zapisany i przywrócony, gdy użyjesz setupWithNavController

Dolna nawigacja

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

dolny pasek nawigacyjny
Rysunek 4. dolny pasek nawigacyjny.

Aby utworzyć dolny pasek nawigacyjny w aplikacji, najpierw zdefiniuj go w sekcji głównej zgodnie z poniższym przykładem:

<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 ramach głównych zajęć wybierz wywołanie setupWithNavController() za pomocą metody onCreate() Twojej głównej aktywności, jak 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);
}

Zaczyna się za Nawigacja 2.4.0-alfa01, stan każdego elementu menu zostanie zapisany i przywrócony, gdy użyjesz setupWithNavController

Obszerny przykład obejmujący dolną nawigację znajdziesz w Przykład zaawansowanej nawigacji dotyczącej komponentów architektury Androida w GitHubie.

Wykrywaj zdarzenia nawigacji

Interakcja z NavController to główna metoda nawigacji między miejscami docelowymi. NavController odpowiada za zastąpienie treści NavHost z nowym miejscem docelowym. W wielu przypadkach elementy interfejsu, takie jak górny pasek aplikacji czy inne stałe elementy sterujące nawigacji, np. BottomNavigationBar, są dostępne na zewnątrz NavHost i trzeba je aktualizować, gdy poruszasz się między miejscami docelowymi.

NavController oferuje interfejs OnDestinationChangedListener, jest wywoływane, gdy aktualny cel podróży u operatora NavController lub jego argumenty ulegną zmianie. Nowego detektora można zarejestrować w addOnDestinationChangedListener() . Pamiętaj, że podczas wywoływania funkcji addOnDestinationChangedListener(), jeśli istnieje aktualne miejsce docelowe, zostanie ona natychmiast wysłana do detektora.

NavigationUI używa OnDestinationChangedListener, aby utworzyć ten wspólny interfejs z myślą o nawigacji. Pamiętaj jednak, że możesz też użyć OnDestinationChangedListener może samodzielnie utworzyć dowolny niestandardowy interfejs lub firmę i rozpoznaje logikę zdarzeń nawigacji.

Możesz na przykład mieć typowe elementy interfejsu, w których chcesz je wyświetlać. wybrane obszary aplikacji, a jednocześnie ukrywając je w innych. Korzystanie z własnych OnDestinationChangedListener, możesz wybiórczo pokazywać lub ukrywać te UI na podstawie 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);
       }
   }
});

Detektory oparte na argumentach

Możesz też użyć argumentów z wartościami domyślnymi w wykres nawigacyjny, który może być używany przez odpowiedni kontroler interfejsu użytkownika aby zaktualizować jego stan. Na przykład, zamiast oprzeć logikę na OnDestinationChangedListener w identyfikatorze miejsca docelowego (zgodnie z poprzednim) na przykład możemy 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, gdy: w drodze do celu, ale jako sposób dołączenia dodatkowych informacji do miejsca docelowego za pomocą defaultValue. W tym przypadku wartość wskazuje, czy pasek aplikacji powinien być wyświetlany w tym miejscu docelowym.

Możemy teraz dodać OnDestinationChangedListener w 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 po każdej zmianie miejsca docelowego nawigacji. Activity może teraz aktualizować stan lub widoczność komponentów UI posiadanego przez nią klienta na podstawie argumentów otrzymanych w wywołaniu zwrotnym.

Jedną z zalet tego podejścia jest to, że Activity widzi tylko argumentów na wykresie nawigacyjnym i nie zna poszczególnych elementów Fragment rolami i obowiązkami. Podobnie poszczególne fragmenty nie mają informacji o elemencie Activity i należących do niego komponentach interfejsu.

Dodatkowe materiały

Aby dowiedzieć się więcej o nawigacji, zapoznaj się z dodatkowymi materiałami poniżej.

Próbki

Ćwiczenia z programowania

Posty na blogu

Filmy