Навигация по Android Jetpack - Уведомление снизу Навигация о правильном предмете

Я столкнулся с проблемой, когда пользовательский интерфейс навигации не выбирает правильный нижний элемент представления навигации при глубокой привязке к фрагменту 2-го уровня.

Вот что я имею в виду:

  • select фрагмент_читая_списки: выбран правильный нижний элемент навигации
  • перейти от фрагмента_читания_ списков -> фрагмент_открытия_ландинга: выбран правильный нижний элемент навигации
  • глубокая ссылка на фрагмент_читая_списки: выбран правильный нижний элемент навигации
  • !! глубокая ссылка на frag_discover_landing: правильный нижний навигационный элемент НЕ выбран!!

Что происходит, когда я делаю глубокую ссылку на frag_discover_landing? Нижний элемент навигации по умолчанию выбран.

Есть ли способ уведомить нижний навигационный адаптер о том, какой пункт СЛЕДУЕТ выбрать в этом случае?

Вот мой навигационный график:

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mobile_navigation"
    app:startDestination="@id/fragment_home">

    <fragment
        android:id="@+id/fragment_home"
        android:name="com.my.app.fragments.HomeFragment"
        android:label="@string/nav_home"
        tools:layout="@layout/home_fragment">
        <action
            android:id="@+id/action_fragment_home_to_fragment_browse_categories"
            app:destination="@id/fragment_browse_categories" />
    </fragment>

    <fragment
        android:id="@+id/fragment_browse_categories"
        android:name="com.my.app.fragments.BrowseCategoriesFragment"
        android:label="@string/discover_default_header"
        tools:layout="@layout/browse_categories_fragment" />

    <fragment
        android:id="@+id/fragment_reading_lists"
        android:name="com.my.app.fragments.ReadingListHubFragment"
        android:label="@string/nav_readinglists"
        tools:layout="@layout/readinglists_landing">
        <action
            android:id="@+id/action_fragment_reading_lists_to_fragment_discover_landing"
            app:destination="@id/fragment_discover_landing" />
    </fragment>

    <fragment
        android:id="@+id/fragment_browse_library"
        android:name="com.my.app.fragments.BrowseLibraryFragment"
        android:label="@string/nav_library"
        tools:layout="@layout/fragment_mylibrary_all" />

    <fragment
        android:id="@+id/fragment_downloads"
        android:name="com.my.app.fragments.DownloadsFragment"
        android:label="@string/nav_downloads"
        tools:layout="@layout/fragment_mylibrary_offline" />

    <fragment
        android:id="@+id/fragment_discover_landing"
        android:name="com.my.app.fragments.DiscoverLandingFragment"
        android:label="@string/nav_discover_landing"
        tools:layout="@layout/discover_landing_fragment">

        <action
            android:id="@+id/fragment_discover_landing_back_action"
            app:popUpTo="@id/fragment_reading_lists"
            app:popUpToInclusive="false" />
        <argument
            android:name="category"
            android:defaultValue="Latest"
            app:argType="string" />
        <argument
            android:name="searchText"
            app:argType="string" />
        <argument
            android:name="searchMode"
            android:defaultValue="false"
            app:argType="boolean" />
        <deepLink
            android:id="@+id/discover_landing_category"
            app:uri="myApp://discover/category?name={category}" />
    </fragment>
</navigation>

ПОБОЧНОЕ ПРИМЕЧАНИЕ: ни один из этих фрагментов не является начальным пунктом назначения. Это домашний фрагмент, который является item1 в нижней части навигации. Fragment_reading_lists - первый фрагмент для item2 в нижней панели навигации.

1 ответ

В соответствии с документацией Deep Link:

Когда пользователь открывает ваше приложение через явную глубокую ссылку, задний стек заданий очищается и заменяется назначением глубокой ссылки. При вложении графиков начальный пункт назначения с каждого уровня вложенности, то есть начальный пункт назначения от каждого элемента в иерархии, также добавляется в стек.

Поэтому, когда вы глубоко ссылку на fragment_discover_landingзадний стек mobile_navigation, fragment_home, затем fragment_discover_landing, поскольку fragment_reading_lists это не startDestination графика, он не добавляется в задний стек и, следовательно, OnDestinationChangedListener тот setupWithNavController использует для выбора соответствующей вкладки, никогда не видит этот пункт назначения.

Если ты хочешь fragment_reading_lists чтобы быть в вашем заднем стеке, он должен быть startDestination вложенного графа, который содержит ваш fragment_discover_landing место назначения:

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mobile_navigation"
    app:startDestination="@id/fragment_home">

    <fragment
        android:id="@+id/fragment_home"
        android:name="com.my.app.fragments.HomeFragment"
        android:label="@string/nav_home"
        tools:layout="@layout/home_fragment">
        <action
            android:id="@+id/action_fragment_home_to_fragment_browse_categories"
            app:destination="@id/fragment_browse_categories" />
    </fragment>

    <fragment
        android:id="@+id/fragment_browse_categories"
        android:name="com.my.app.fragments.BrowseCategoriesFragment"
        android:label="@string/discover_default_header"
        tools:layout="@layout/browse_categories_fragment" />

    <!-- Make sure to change your menu.xml to use @+id/reading_lists -->
    <navigation
        android:id="@+id/reading_lists"
        app:startDestination="@+id/fragment_reading_lists">

        <fragment
            android:id="@+id/fragment_reading_lists"
            android:name="com.my.app.fragments.ReadingListHubFragment"
            android:label="@string/nav_readinglists"
            tools:layout="@layout/readinglists_landing">
            <action
                android:id="@+id/action_fragment_reading_lists_to_fragment_discover_landing"
                app:destination="@id/fragment_discover_landing" />
        </fragment>

        <fragment
            android:id="@+id/fragment_discover_landing"
            android:name="com.my.app.fragments.DiscoverLandingFragment"
            android:label="@string/nav_discover_landing"
            tools:layout="@layout/discover_landing_fragment">

            <action
                android:id="@+id/fragment_discover_landing_back_action"
                app:popUpTo="@id/fragment_reading_lists"
                app:popUpToInclusive="false" />
            <argument
                android:name="category"
                android:defaultValue="Latest"
                app:argType="string" />
            <argument
                android:name="searchText"
                app:argType="string" />
            <argument
                android:name="searchMode"
                android:defaultValue="false"
                app:argType="boolean" />
            <deepLink
                android:id="@+id/discover_landing_category"
                app:uri="myApp://discover/category?name={category}" />
        </fragment>

    </navigation>

    <fragment
        android:id="@+id/fragment_browse_library"
        android:name="com.my.app.fragments.BrowseLibraryFragment"
        android:label="@string/nav_library"
        tools:layout="@layout/fragment_mylibrary_all" />

    <fragment
        android:id="@+id/fragment_downloads"
        android:name="com.my.app.fragments.DownloadsFragment"
        android:label="@string/nav_downloads"
        tools:layout="@layout/fragment_mylibrary_offline" />
</navigation>

Обратите внимание, что в соответствии с документацией навигационных графиков Design:

[вложенные графы] также обеспечивают уровень инкапсуляции - места назначения вне вложенного графа не имеют прямого доступа ни к одному из мест назначения во вложенном графе.

Так что это будет иметь побочный эффект, так что ваш fragment_discover_landing не будет виден ни одному месту назначения за пределами fragment_reading_lists, Эта проблема отслеживает навигацию по глубокой ссылке, которая позволит вам получить доступ к пункту назначения из любой точки вашего приложения по URL-ссылке, которую вы прикрепили к нему, но она пока недоступна.