【问题标题】:Android - Using Muiltiple Navigation Graphs Is Not WorkingAndroid - 使用多个导航图不起作用
【发布时间】:2021-01-24 22:50:58
【问题描述】:

我正在使用谷歌解决BottomNavigationView和导航组件的片段状态问题,它使用多个导航图以及这个扩展功能:https://github.com/android/architecture-components-samples/blob/master/NavigationAdvancedSample/app/src/main/java/com/example/android/navigationadvancedsample/NavigationExtensions.kt

但是,问题是初始导航图与我提供的完全不同(从日志中可以看到,它的 id 是 2131230909) 我不知道它从哪里得到这个ID。因此, selectedId if check (if (this.selectedItemId == graphId) ) 在扩展函数中失败,因此它永远不会附加 navHostFragment。 设置 BottomNav 的 selectedItem 也不起作用:binding.bottomNavView.setSelectedItemId( R.navigation.game_list)



这是我的日志,如果您知道为什么会发生这种情况,请告诉我:

D/NavigationExtensionsKt: creating NavHostFragment with id: 2131623937
D/NavigationExtensionsKt: detaching NavHostFragment with id: 2131623937
D/NavigationExtensionsKt: creating NavHostFragment with id: 2131623936
D/NavigationExtensionsKt: detaching NavHostFragment with id: 2131623936
D/NavigationExtensionsKt: selectedItemId: 2131230909, firstFragmentTag: bottomNavigation#0, isOnFirstFragment: false

游戏列表导航图

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/game_list"
    app:startDestination="@id/gameListFragment">

    <fragment
        android:id="@+id/gameListFragment"
        android:name="com.developerkurt.gamedatabase.ui.GameListFragment"
        android:label="GameListFragment"
        tools:layout="@layout/game_list_fragment">
        <action
            android:id="@+id/action_gameListFragment_to_gameDetailsFragment"
            app:destination="@id/gameDetailsFragment" />
    </fragment>

    <fragment
        android:id="@+id/gameDetailsFragment"
        android:name="com.developerkurt.gamedatabase.ui.GameDetailsFragment"
        android:label="GameDetailsFragment"
        tools:layout="@layout/game_details_fragment_motion_scene_end">
        <argument
            android:name="id"
            app:argType="integer" />
        <argument
            android:name="isInFavorites"
            app:argType="boolean" />
    </fragment>
</navigation>

最喜欢的游戏导航图

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/fav_games"
    app:startDestination="@id/favoriteGamesFragment">

    <fragment
        android:id="@+id/favoriteGamesFragment"
        android:name="com.developerkurt.gamedatabase.ui.FavoriteGamesFragment"
        android:label="FavoriteGamesFragment"
        tools:layout="@layout/favorite_games_fragment">
        <action
            android:id="@+id/action_favoriteGamesFragment_to_gameDetailsFragment"
            app:destination="@id/gameDetailsFragment" />
    </fragment>
    <fragment
        android:id="@+id/gameDetailsFragment"
        android:name="com.developerkurt.gamedatabase.ui.GameDetailsFragment"
        android:label="GameDetailsFragment"
        tools:layout="@layout/game_details_fragment_motion_scene_end">
        <argument
            android:name="id"
            app:argType="integer" />
        <argument
            android:name="isInFavorites"
            app:argType="boolean" />
    </fragment>
</navigation>

MainActivity

class MainActivity : AppCompatActivity()
{

    private lateinit var binding: ActivityMainBinding

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

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        if (savedInstanceState == null)
        {
            setupBottomNavigationBar()
        } // Else, need to wait for onRestoreInstanceState
    }


    override fun onRestoreInstanceState(savedInstanceState: Bundle)
    {
        super.onRestoreInstanceState(savedInstanceState)
        // Now that BottomNavigationBar has restored its instance state
        // and its selectedItemId, we can proceed with setting up the
        // BottomNavigationBar with Navigation
        setupBottomNavigationBar()
    }

    fun setupBottomNavigationBar()
    {
        binding.bottomNavView.visibility = View.VISIBLE

        val navGraphIds = listOf(R.navigation.game_list, R.navigation.fav_games)


        // Setup the bottom navigation view with a list of navigation graphs
        binding.bottomNavView.setupWithNavController(
                navGraphIds = navGraphIds,
                fragmentManager = supportFragmentManager,
                containerId = R.id.fragment_container,
                intent = intent)
        
    }
}

MainActivity 布局

  <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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/main_activity"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.MainActivity">
    
    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragment_container"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"

        app:layout_constraintBottom_toTopOf="@+id/bottom_nav_view"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />


    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_nav_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"

        app:layout_constraintBottom_toBottomOf="parent"
        app:menu="@menu/bottom_nav_menu" />


</androidx.constraintlayout.widget.ConstraintLayout>

底部导航菜单

  <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/bottom_nav_menu">
    
        <item
            android:id="@+id/gameListFragment"
            android:icon="@drawable/ic_home"
            android:menuCategory="secondary"
            android:title="@string/home" />
        <item
            android:id="@+id/favoriteGamesFragment"
            android:icon="@drawable/ic_favorite"
            android:menuCategory="secondary"
            android:title="@string/favorites" />
</menu>

【问题讨论】:

  • 请附上您的@menu/bottom_nav_menu

标签: java android android-layout kotlin android-fragments


【解决方案1】:

您为菜单项使用了错误的 ID - NavigationExtensions 将您的菜单 ID 与根 &lt;navigation&gt; 元素上的 android:id 进行比较,不是开始的 ID这些图表的目的地。

因此,您应该为菜单项使用android:id="@+id/game_list"android:id="@+id/fav_games" 以匹配图表ID。

【讨论】:

  • 这就是我花了一整天的时间……嗯,谢谢
  • 嗯,片段的状态永远不会被保存。你知道为什么会这样吗?
  • 这听起来像是一个完全不同的问题,需要非常不同的代码(即,不保存其状态的特定片段的代码)。我会首先检查诸如旋转您的设备并使用“不保留活动”之类的情况,以确保您在片段级别正确保存了您的状态。
【解决方案2】:

可以将一系列目的地分组到称为根图的父导航图中的嵌套图。嵌套图表对于组织、优化和重用应用 UI 的各个部分很有用。

&lt;include app:graph=”@navigation/B_nav_graph” /&gt; &lt;include app:graph=”@navigation/C_nav_graph” /&gt;

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/A_nav_graph"
    app:startDestination="@id/A1_fragment">
    <include app:graph="@navigation/B_nav_graph" />
    <include app:graph="@navigation/C_nav_graph" />
    <fragment
        android:id="@+id/A1_fragment"
        android:name="com.example.multiplenavigation.A_nav_graph.A1"
        android:label="A1"
        tools:layout="@layout/fragment_A1">
        <action
            android:id="@+id/A1_to_B_nav_graph"
            app:destination="@id/B_nav_graph" />
        <action
            android:id="@+id/A1_to_C_nav_graph"
            app:destination="@id/C_nav_graph" />
        <action
            android:id="@+id/A1_to_A2"
            app:destination="@id/A2_fragment" />
    </fragment>
    <fragment
        android:id="@+id/A2_fragment"
        android:name="com.example.multiplenavigation.A_nav_graph.A2"
        android:label="A2"
        tools:layout="@layout/fragment_A2" />
</navigation>

我们的 B_nav_graph.xml 文件看起来像 -

    <?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/B_nav_graph"
    app:startDestination="@id/B1_fragment">
    <fragment
        android:id="@+id/B1_fragment"
        android:name="com.example.multiplenavigation.B_nav_graph.B1 "
        android:label="B1"
        tools:layout="@layout/fragment_B1">
        <action
            android:id="@+id/B1_to_B2_fragment"
            app:destination="@id/B2_fragment" />
    </fragment>
    <fragment
        android:id="@+id/B2_fragment"
        android:name="com.example.multiplenavigation.B_nav_graph.B2"
        android:label="B2"
        tools:layout="@layout/fragment_B2" >
        <action
            android:id="@+id/B2_to_A1"
            app:destination="@id/A_nav_graph"
            app:popUpToInclusive="true"
            app:popUpTo="@id/A_nav_graph"/>
    </fragment>
</navigation>

而 C_nav_graph.xml 文件看起来像 -

 <?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/C_nav_graph"
    app:startDestination="@id/C1_fragment">
    <fragment
        android:id="@+id/C1_fragment"
        android:name="com.example.multiplenavigation.C_nav_graph.C1 "
        android:label="C1"
        tools:layout="@layout/fragment_C1">
        <action
            android:id="@+id/C1_to_C2_fragment"
            app:destination="@id/C2_fragment" />
    </fragment>
    <fragment
        android:id="@+id/C2_fragment"
        android:name="com.example.multiplenavigation.C_nav_graph.C2"
        android:label="C2"
        tools:layout="@layout/fragment_C2" >
        <action
            android:id="@+id/C2_to_A1"
            app:destination="@id/A_nav_graph"
            app:popUpToInclusive="true"
            app:popUpTo="@id/A_nav_graph"/>
    </fragment>
</navigation>

这里是a link!还有一个参考示例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-23
    相关资源
    最近更新 更多