android - 非法状态异常 : Activity does not have a NavController set on

标签 android android-fragments navigation-drawer android-architecture-components android-architecture-navigation

这个问题在这里已经有了答案:





FragmentContainerView using findNavController

(8 个回答)


去年关闭。




我尝试编写一个 Android 应用程序,它使用来自 androidx 的导航组件、工具栏和抽屉布局从左侧滑入设置菜单。我按照指南 Get started with the Navigation component并尝试使用本指南 Update UI components with NavigationUI 添加顶部应用栏和设置.
当我的应用程序启动时,会引发以下异常:

java.lang.IllegalStateException: Activity ....MainActivity@e686cd8 does not have a NavController set on 2131230993
旁注:如果我打开 nav_graph.xml在设计模式下,主机 Pane 报告“未找到 NavHostFragments。此导航图必须从布局中的 NavHostFragment 引用才能访问。”也许这个错误和异常是相关的并且共享相同的根本原因。但是,我的导航图被 NavHostFragment 引用。不过,见下文。
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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/drawer_layout"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:fitsSystemWindows="true"
  tools:context=".MainActivity">

  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/main_toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:theme="?attr/actionBarTheme" />

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph" />
  </LinearLayout>

  <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"
    app:menu="@menu/drawer_view"
    app:headerLayout="@layout/nav_header" />
</androidx.drawerlayout.widget.DrawerLayout>
这种布局
  • 包含 FragmentContainerView
  • 引用资料 @navigation/nav_graph (粘贴在下面)
  • 包含 NavigationView
  • 引用资料 @layout/nav_header (粘贴在下面)
  • 引用资料 @menu/drawer_view (粘贴在下面)

  • nav_header.xml:
    <?xml version="1.0" encoding="utf-8"?>
    <android.widget.LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="192dp"
      android:background="?attr/colorPrimaryDark"
      android:gravity="bottom"
      android:padding="16dp"
      android:theme="@style/ThemeOverlay.AppCompat.Dark">
    
      <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/app_name"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
    </android.widget.LinearLayout>
    
    抽屉 View .xml:
    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android">
      <group android:checkableBehavior="single">
        <item
          android:id="@+id/nav_home"
          android:icon="@drawable/ic_home"
          android:title="@string/home"/>
        <item
          android:id="@+id/nav_settings"
          android:icon="@drawable/ic_settings"
          android:title="@string/settings" />
      </group>
    </menu>
    
    fragment_home.xml:
    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      tools:context=".HomeFragment"/>
    
    此 fragment 由 nav_graph 引用(粘贴在下面)作为主 fragment (起始目的地)。
    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/nav_graph"
      app:startDestination="@id/homeFragment">
    
      <fragment
        android:id="@+id/homeFragment"
        android:name="de.mhnnet.lychee4android.HomeFragment"
        android:label="fragment_home"
        tools:layout="@layout/fragment_home" />
    </navigation>
    
    MainActivity.java:
    protected void onCreate( Bundle savedInstanceState ) {
      super.onCreate( 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.main_toolbar );
      NavigationUI.setupWithNavController( toolbar, navController, appBarConfiguration );
    }
    
    补充说明:
    我已经找到了一些提示 androidx.fragment.app.FragmentContainerView应替换为 fragment .但是,这感觉不对,因为 linter 建议使用 FragmentContainerView而不是 fragmentofficial Android docs使用 FragmentContainerView , 也。

    最佳答案

    可以得到Nav Controller在您的 Activity 中替换您的

        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_graph" />
    
    
        <fragment
            android:id="@+id/nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_graph" />
    
    
    但正如 lint 建议使用 FragmentContainerView 更改 fragment 使用以下代码获取Nav Controller在你的 Activity 中。
    
            NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
    
            if (navHostFragment != null) {
    
                NavController navController = navHostFragment.getNavController();
    
                // Setup NavigationUI here
    
            }
    
    

    关于android - 非法状态异常 : Activity does not have a NavController set on,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66304330/

    相关文章:

    android - 制作带有白色圆形边框的圆形图像

    android-fragments - 如何使用导航组件配置DrawerLayout

    android - 在后台堆栈中添加同一 fragment 的多个实例,先前添加的实例的数据仍然存在

    android - 如何在android中的 fragment 上创建抽屉导航

    android - Lollipop 商店中的抽屉指示器

    android - 在包 'showAsAction' 中找不到属性 'com.javatechig.todo' 的资源标识符

    安卓 NFC : Exception "transceive failed" when using transceive()

    android - 单击箭头图标时如何在抽屉导航的 Android 中使用 onBackPressed?

    java - android中的访问/数据文件夹文件

    Android - 如何显示包含从 fragment 中获取的字符串的 snackbar