Null NavHostFragment/NavController与FragmentContainerView [英] Null NavHostFragment/NavController with FragmentContainerView

本文介绍了Null NavHostFragment/NavController与FragmentContainerView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

预期

使用导航UI的 BottomNavigationView FragmentContainerView 创建底部应用栏导航,类似于示例应用 BottomNavigationViewSample 存储库中找到..

错误

2020-05-15 12:39:19.117 18747-18747/com.example.bottomnavigationviewsample E/AndroidRuntime:FATAL EXCEPTION:main流程:com.example.bottomnavigationviewsample,PID:18747java.lang.RuntimeException:无法启动活动ComponentInfo {com.example.bottomnavigationviewsample/com.example.bottomnavigationviewsample.MainActivity}: kotlin.TypeCastException:无法将null强制转换为非null类型的androidx.navigation.fragment.NavHostFragment在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)在android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)在android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)在android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:2016)在android.os.Handler.dispatchMessage(Handler.java:107)在android.os.Looper.loop(Looper.java:214)在android.app.ActivityThread.main(ActivityThread.java:7356)在java.lang.reflect.Method.invoke(本机方法)在com.android.internal.os.RuntimeInit $ MethodAndArgsCaller.run(RuntimeInit.java:492)在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)原因:kotlin.TypeCastException:无法将null强制转换为非null类型androidx.navigation.fragment.NavHostFragment在com.example.bottomnavigationviewsample.MainActivity.onCreate(MainActivity.kt:16)在android.app.Activity.performCreate(Activity.java:7802)在android.app.Activity.performCreate(Activity.java:7791)在android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)在android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)在android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)在android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:2016)在android.os.Handler.dispatchMessage(Handler.java:107)在android.os.Looper.loop(Looper.java:214)在android.app.ActivityThread.main(ActivityThread.java:7356)在java.lang.reflect.Method.invoke(本机方法)在com.android.internal.os.RuntimeInit $ MethodAndArgsCaller.run(RuntimeInit.java:492)在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)2020-05-15 12:39:19.132 18747-18747/com.example.bottomnavigationviewsample I/Process:正在发送信号.PID:18747 SIG:9

实施

  1. 为第一个视图 home.xml 创建导航图,以显示在 app> res>导航 BottomNavigationView 中>.

    a.当提示您添加项目依赖项时,选择确定.

    b.将 kotlinOptions {jvmTarget ='1.8'} 添加到 build.gradle(:someAppModule)中,以为 AppBarConfiguration 启用内联字节码.

    c.将片段添加到 home.xml 中,以显示在 BottomNavigationView 中.

home.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/home"app:startDestination ="@ id/homeFragment"><片段android:id ="@ + id/homeFragment"android:name ="com.example.bottomnavigationviewsample.HomeFragment"android:label ="fragment_home"工具:layout ="@ layout/fragment_home"/></导航> 

build.gradle

  apply插件:"com.android.application"套用外挂程式:'kotlin-android'应用插件:"kotlin-android-extensions"安卓 {compileSdkVersion 29buildToolsVersion"29.0.3"kotlinOptions {jvmTarget ='1.8'}defaultConfig {applicationId"com.example.bottomnavigationviewsample"minSdkVersion 21targetSdkVersion 29版本代码1versionName"1.0"testInstrumentationRunner"androidx.test.runner.AndroidJUnitRunner"}buildTypes {释放 {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),'proguard-rules.pro'}}}依赖项{实现fileTree(dir:'libs',包括:['* .jar'])实现"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$ kotlin_version"实现'androidx.appcompat:appcompat:1.1.0'实现'androidx.core:core-ktx:1.2.0'实现'androidx.constraintlayout:constraintlayout:1.1.3'testImplementation'junit:junit:4.12'androidTestImplementation'androidx.test.ext:junit:1.1.1'androidTestImplementation'androidx.test.espresso:espresso-core:3.2.0'实现'androidx.navigation:navigation-fragment-ktx:2.2.2'实现'androidx.navigation:navigation-ui-ktx:2.2.2'} 

  1. app> res>菜单下,为 BottomNavigationView bottom_nav.xml 创建菜单.

    a.为菜单 id title 添加字符串值.

    b.为菜单 icon 添加矢量drawable.

bottom_nav.xml

 <?xml version ="1.0" encoding ="utf-8"?>< menu xmlns:android ="http://schemas.android.com/apk/res/android"><项目android:id ="@ + id/home"android:icon ="@ drawable/ic_home_black_24dp"android:contentDescription ="@ string/cd_home"android:title ="@ string/title_home"/></菜单> 

  1. FragmentContainerView BottomNavigationView 添加到 MainActivity.kt activity_main.xml 布局中.

activity_main.xml

 < LinearLayout 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:orientation ="vertical"工具:context =.MainActivity">< androidx.fragment.app.FragmentContainerViewandroid:id ="@ + id/nav_host_container"android:layout_width ="match_parent"android:layout_height ="0dp"android:layout_weight ="1"/>< com.google.android.material.bottomnavigation.BottomNavigationViewandroid:id ="@ + id/bottom_nav"android:layout_width ="match_parent"android:layout_height ="wrap_content"app:menu ="@ menu/bottom_nav"/></LinearLayout> 

  1. MainActivity.kt 中启用 BottomNavigationView .

    a.创建 AppBarConfiguration .请参阅:使用NaviationUI更新UI组件> AppBarConfiguration

    b.创建 NavHostFragment NavController .请参阅:适用于使用findNavController的FragmentContainerView的StackOverflow解决方案

    c.设置操作栏导航.

    d.设置 BottomNavigationView 导航.请参阅:使用NavigationUI> 底部导航

MainActivity.kt

 程序包com.example.bottomnavigationviewsample导入android.os.Bundle导入androidx.appcompat.app.AppCompatActivity导入androidx.navigation.fragment.NavHostFragment导入androidx.navigation.ui.AppBarConfiguration导入androidx.navigation.ui.setupActionBarWithNavController导入androidx.navigation.ui.setupWithNavController导入kotlinx.android.synthetic.main.activity_main.*MainActivity类:AppCompatActivity(){重写fun onCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val appBarConfiguration = AppBarConfiguration(setOf(R.id.home))val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_container)as NavHostFragmentval navController = navHostFragment.navControllersetupActionBarWithNavController(navController,appBarConfiguration)bottom_nav.setupWithNavController(navController)}} 

尝试的解决方案

  1. 使用 findNavController(R.id.nav_host_container)创建 NavController ,如

    我也遇到了这个问题.我的错误是我没有在导航文件中输入正确的导航标签ID.请注意,该ID必须等于菜单项的ID.

    在导航文件(navigation/home.xml)中:

     <导航android:id ="@@ id/home";...> 

    和菜单文件(menu/bottom_nav.xml):

     <项目android:id ="@@ id/home";.../> 

    Expected

    Create bottom app bar navigation using Navigation UI's BottomNavigationView and FragmentContainerView similar to the sample app NavigationAdavancedSample.

    Note, NavigationAndvancedSample app does not appear to use the same implementation as described in the documentation as it has a workaround implementation using the custom extension method setupWithNavController.

    Observed

    Null NavHostFragment when creating the BottomNavigationView in the MainActivity.kt with a FragmentContainerView.

    The reproducible error and full code sample is available in the BottomNavigationViewSample repository.

    Error

    2020-05-15 12:39:19.117 18747-18747/com.example.bottomnavigationviewsample E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.bottomnavigationviewsample, PID: 18747 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.bottomnavigationviewsample/com.example.bottomnavigationviewsample.MainActivity}: kotlin.TypeCastException: null cannot be cast to non-null type androidx.navigation.fragment.NavHostFragment at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) at android.os.Handler.dispatchMessage(Handler.java:107) at android.os.Looper.loop(Looper.java:214) at android.app.ActivityThread.main(ActivityThread.java:7356) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) Caused by: kotlin.TypeCastException: null cannot be cast to non-null type androidx.navigation.fragment.NavHostFragment at com.example.bottomnavigationviewsample.MainActivity.onCreate(MainActivity.kt:16) at android.app.Activity.performCreate(Activity.java:7802) at android.app.Activity.performCreate(Activity.java:7791) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)  at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)  at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)  at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)  at android.os.Handler.dispatchMessage(Handler.java:107)  at android.os.Looper.loop(Looper.java:214)  at android.app.ActivityThread.main(ActivityThread.java:7356)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)  2020-05-15 12:39:19.132 18747-18747/com.example.bottomnavigationviewsample I/Process: Sending signal. PID: 18747 SIG: 9

    Implementation

    1. Create a navigation graph for the first view, home.xml, to show in the BottomNavigationView under app > res > navigation.

      a. When prompted to Add Project Dependency, select OK.

      b. Add kotlinOptions { jvmTarget = '1.8' } to build.gradle (:someAppModule) to enable inline bytecode for the AppBarConfiguration.

      c. Add a fragment to home.xml to display in the BottomNavigationView.

    home.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/home"
        app:startDestination="@id/homeFragment">
    
        <fragment
            android:id="@+id/homeFragment"
            android:name="com.example.bottomnavigationviewsample.HomeFragment"
            android:label="fragment_home"
            tools:layout="@layout/fragment_home" />
    </navigation>
    

    build.gradle

    apply plugin: 'com.android.application'
    apply plugin: 'kotlin-android'
    apply plugin: 'kotlin-android-extensions'
    
    android {
        compileSdkVersion 29
        buildToolsVersion "29.0.3"
    
        kotlinOptions { jvmTarget = '1.8' }
    
        defaultConfig {
            applicationId "com.example.bottomnavigationviewsample"
            minSdkVersion 21
            targetSdkVersion 29
            versionCode 1
            versionName "1.0"
    
            testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        }
    
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            }
        }
    
    }
    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
        implementation 'androidx.appcompat:appcompat:1.1.0'
        implementation 'androidx.core:core-ktx:1.2.0'
        implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'androidx.test.ext:junit:1.1.1'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
        implementation 'androidx.navigation:navigation-fragment-ktx:2.2.2'
        implementation 'androidx.navigation:navigation-ui-ktx:2.2.2'
    }
    
    

    1. Create a menu for the BottomNavigationView, bottom_nav.xml, under app > res > menu.

      a. Add string values for the menu id and title.

      b. Add vector drawable for the menu icon.

    bottom_nav.xml

    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android">
            <item
                android:id="@+id/home"
                android:icon="@drawable/ic_home_black_24dp"
                android:contentDescription="@string/cd_home"
                android:title="@string/title_home" />
    </menu>
    

    1. Add the FragmentContainerView and BottomNavigationView to MainActivity.kt's activity_main.xml layout.

    activity_main.xml

    <LinearLayout 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:orientation="vertical"
        tools:context=".MainActivity">
    
        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/nav_host_container"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1" />
    
        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/bottom_nav"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:menu="@menu/bottom_nav"/>
    </LinearLayout>
    

    1. Enable the BottomNavigationView in MainActivity.kt.

      a. Create AppBarConfiguration. See: Update UI components with NaviationUI > AppBarConfiguration

      b. Create the NavHostFragment and NavController. See: StackOverflow solution for FragmentContainerView using findNavController

      c. Set the action bar navigation.

      d. Set the BottomNavigationView navigation. See: Update UI components with NavigationUI > Bottom navigation

    MainActivity.kt

    package com.example.bottomnavigationviewsample
    
    import android.os.Bundle
    import androidx.appcompat.app.AppCompatActivity
    import androidx.navigation.fragment.NavHostFragment
    import androidx.navigation.ui.AppBarConfiguration
    import androidx.navigation.ui.setupActionBarWithNavController
    import androidx.navigation.ui.setupWithNavController
    import kotlinx.android.synthetic.main.activity_main.*
    
    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            val appBarConfiguration = AppBarConfiguration(setOf(R.id.home))
    
            val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_container) as NavHostFragment
            val navController = navHostFragment.navController
    
            setupActionBarWithNavController(navController, appBarConfiguration)
            bottom_nav.setupWithNavController(navController)
        }
    }
    

    Attempted Solutions

    1. Create the NavController with findNavController(R.id.nav_host_container) as outlined in the documentation.

    2. Implement a fragment view instead of FragmentContainerView in activity_main.xml.

    activity_main.xml

    <LinearLayout 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:orientation="vertical"
        tools:context=".MainActivity">
    
        <fragment
            android:id="@+id/nav_host_container"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1" />
    
        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/bottom_nav"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:menu="@menu/bottom_nav"/>
    </LinearLayout>
    

    解决方案

    I also had this problem. My mistake was that I did not enter the correct ID for navigation tag in navigation files. Note that the ID must be equal to the ID of the menu items.

    in navigation file (navigation/home.xml):

    <navigation
    android:id="@+id/home" ... >
    

    and in menu file (menu/bottom_nav.xml):

     <item
        android:id="@+id/home" ... />
    

    这篇关于Null NavHostFragment/NavController与FragmentContainerView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆