【问题标题】:Bottom navigation: NavigationUI.setupActionBarWithNavController() not working for fragment exchanging底部导航:NavigationUI.setupActionBarWithNavController() 不适用于片段交换
【发布时间】:2020-09-07 16:37:37
【问题描述】:

背景: (如果你不想知道我是怎么得到问题的,可以忽略。只是关于 Android Studio 模板活动的一些问题)

我一直在研究底部导航,并尝试从 Android Studio 默认创建的底部导航 Activity 模板中复制 MainActivity.java 的代码。



我还从 Android Studio 找到了这个 UI 的文档。 Bottom Navigation
基本上MainActivity中调用底部导航交互的主要代码应该是这样的:

    AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
            R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications)
            .build();
    NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
    NavigationUI.setupWithNavController(navView, navController);


我的问题:
我的底部导航 xml 工作完美。但我刚刚发现NavigationUI.setupActionBarWithNavController()NavigationUI.setupWithNavController() 不起作用。每当我运行我的应用程序时,它就会闪烁并停止。有点奇怪,但我相信这两种方法是底部导航的官方用法。

HomePage.xml

<?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:layout_width="match_parent"
android:fitsSystemWindows="true"
android:layout_height="match_parent">

<com.google.android.material.appbar.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.AppBarOverlay"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="#267A9E"
        app:popupTheme="@style/AppTheme.PopupOverlay" />

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


<fragment
    android:id="@+id/frag_container"
    android:name="androidx.navigation.fragment.NavHostFragment"
    android:layout_width="match_parent"
    android:layout_height="612dp"
    app:defaultNavHost="true"
    app:layout_constraintBottom_toBottomOf="@id/bottom_navi"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:navGraph="@navigation/nav_graph" />

<com.google.android.material.bottomnavigation.BottomNavigationView
    android:id="@+id/bottom_navi"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?android:attr/windowBackground"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:menu="@menu/bottom_navigation" />

<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:id="@+id/fab"
    android:layout_width="53dp"
    android:layout_height="56dp"
    android:layout_gravity="bottom|end"
    android:layout_margin="@dimen/fab_margin"
    app:backgroundTint="#4a90c9"
    app:layout_constraintBottom_toTopOf="@+id/bottom_navi"
    app:layout_constraintEnd_toEndOf="parent"
    app:srcCompat="@drawable/plus" />


</androidx.constraintlayout.widget.ConstraintLayout>




解决方案:
现在我正在使用传统方式(设置点击侦听器)来正确实现此导航。这是老式的但非常灵活,因为我有我的个性化工具栏和侧边菜单。

  bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
       @Override
       public boolean onNavigationItemSelected(@NonNull MenuItem item) {
           navController= Navigation.findNavController(HomeActivity.this, R.id.frag_container);
            switch (item.getItemId()) {
               case R.id.bottom_navi_intake:
                   navController.navigate(R.id.action_WeightFragment_to_IntakeFragment);
                   break;
               case R.id.bottom_navi_weight:
                   navController.navigate(R.id.action_IntakeFragment_to_WeightFragment);
                   break;
           }
           return true;
       }
   });


R.id.action_...
@navigation/nav.graph.xml 中的操作 ID:

<?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/nav_graph"
app:startDestination="@id/bottom_navi_intake">

<fragment
    android:id="@+id/bottom_navi_intake"
    android:name="com.example.dietdiary.IntakeFragment"
    android:label="@string/first_fragment_label"
    tools:layout="@layout/fragment_intake">

    <action
        android:id="@+id/action_IntakeFragment_to_WeightFragment"
        app:destination="@id/bottom_navi_weight" />
</fragment>
<fragment
    android:id="@+id/bottom_navi_weight"
    android:name="com.example.dietdiary.WeightFragment"
    android:label="@string/second_fragment_label"
    tools:layout="@layout/fragment_weight">

    <action
        android:id="@+id/action_WeightFragment_to_IntakeFragment"
        app:destination="@id/bottom_navi_intake" />
</fragment>


我的最终截图供您参考:

【问题讨论】:

标签: android navigation androidx


【解决方案1】:

我遇到了同样的错误,我通过创建自己的自己的工具栏然后将其设置到支持操作栏来解决它,如下所示。

最初,使用 findviewbyid 或使用 databinding 获取 工具栏 并将其分配给变量。这里我已将其设置为变量工具栏,然后进一步使用它。

setSupportActionBar(toolbar)

然后我们必须将其添加到 appbarconfiguraion 中,如下所示。

toolbar.setupWithNavController(navController, appBarConfiguration)

错误可能是由于工具栏导航视图之间的未建立连接

希望这会有所帮助。

【讨论】:

  • 我已经有了自己的工具栏。但我的错误显示:无法解析方法:setupWithNavController(androidx.navigation.NavController,?)
  • 你能解决这个问题吗,@helen?我也有同样的问题
【解决方案2】:

menu.xml 和 navigation_graph.xml 片段中的 id 应该相同,

下面是我的 menu.xml 文件

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
   <item
      android:id="@+id/home_frag"
      android:icon="@drawable/ic_group_home"
      android:title="@string/title_home" />
   <item
       android:id="@+id/all_game_frag"
       android:icon="@drawable/ic_group_game"
       android:title="@string/title_All_Games" />
</menu>

下面是我的 navigation_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/mobile_navigation"
   app:startDestination="@+id/home_frag">

    <fragment
       android:id="@+id/home_frag"
       android:name="com.legendmame.dinoemulator.classic.ui.home.HomeFragment"
       android:label="@string/title_home"
       tools:layout="@layout/fragment_home" />

   <fragment
      android:id="@+id/all_game_frag"
      android:name="com.legendmame.dinoemulator.classic.ui.allgames.AllGames"
      android:label="@string/title_notifications"
      tools:layout="@layout/fragment_notifications" />
 </navigation>

【讨论】:

    【解决方案3】:

    你好@Helen,让我教你使用 Architectural Component 使用底部导航的正确方法。

    下面是名为 bottom_nav_menu 的菜单布局文件

     <item
            android:id="@+id/homeFragment"
            android:icon="@drawable/ic_home_black_24dp"
            android:title="Home"
            android:menuCategory="secondary"/>
        <item
            android:id="@+id/dashboardFragment"
            android:icon="@drawable/ic_dashboard_black_24dp"
            android:title="Dashboard"
            android:menuCategory="secondary"/>
    

    底部导航会显示Home和Dashboard这两个项目。

    现在让我们开始主要活动

    <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:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white"
        tools:context=".MainActivity">
    
        <fragment
            android:id="@+id/nav_host_fragment"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toTopOf="@+id/bottomNav"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            android:name="androidx.navigation.fragment.NavHostFragment"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_graph"
            />
    
    
        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/bottomNav"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:menu="@menu/bottom_nav_menu"
            android:background="#fff"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    在主要活动中:fragment 将承载两个fragment,BottomNavigationView 将访问菜单bottom_nav_menu 然后您可以创建两个Fragment,一个称为HomeFragment,第二个是DashboardFragment,布局分别称为fragment_home 和fragment_dashboard。

    是时候创建导航图了

    <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/nav_graph"
        app:startDestination="@id/homeFragment">
    
        <fragment
            android:id="@+id/homeFragment"
    
      android:name="raum.muchbeer.bottomnavigationstackoverflow.fragment.HomeFragment"
            android:label="Fragment Home"
            tools:layout="@layout/fragment_home" >
    
        </fragment>
        <fragment
            android:id="@+id/dashboardFragment"
    
     android:name="raum.muchbeer.bottomnavigationstackoverflow.fragment.DashboardFragment"
            android:label="Fragment Dashboard"
            tools:layout="@layout/fragment_dashboard" />
    </navigation>
    

    navGraph 实现了两个片段 HomeFragment 和 DashboardFragment,请注意两个片段的 id,即 homeFragment 和 dashboardFragment 必须与您在 bottom_nav_menu 文件中设置的 id 完全相同。如果您不这样做,那么您将无法浏览这两个片段。

    现在让我们完成 mainactivity,请在 onCreate 中添加以下代码

    BottomNavigationView bottomNavigationView = findViewById(R.id.bottomNav);

    NavController navController = Navigation.findNavController(this, 
    R.id.nav_host_fragment);
    
    NavigationUI.setupWithNavController(bottomNavigationView, navController);
    
    NavigationUI.setupActionBarWithNavController(this, navController);
    

    那么你就完成了,一切顺利。请参考githubhere

    编码愉快!!!

    【讨论】:

    • 您在主要活动中的代码对我有用!谢谢。尽管它仍然没有正确显示我的主页,因为工具栏将标题显示为“第一个片段”而不是我预定义的...无论如何...为什么 Android Studio 的模板有AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder( R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications) .build(); ???这似乎没有用,导致我崩溃
    【解决方案4】:

    你能检查一下你是否有相同的id 用于menu.xmlmobile_navigation.xml 用于该项目。在我的情况下,物品制作原因有不同的id 名称。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-10
      • 2020-11-08
      • 2020-03-23
      相关资源
      最近更新 更多