Null NavHostFragment/NavController与FragmentContainerView [英] Null NavHostFragment/NavController with FragmentContainerView
问题描述
预期
使用导航UI的 BottomNavigationView
和 FragmentContainerView
创建底部应用栏导航,类似于示例应用 文档,因为它具有使用自定义扩展方法 setupWithNavController
的解决方法.
已观察
在 MainActivity.kt 中使用 FragmentContainerView
创建 BottomNavigationView
时, Null NavHostFragment
.
可重现的错误和完整代码示例可在 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
实施
-
为第一个视图 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'}
-
在 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"/></菜单>
- 将
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>
-
在 MainActivity.kt 中启用
BottomNavigationView
.a.创建
AppBarConfiguration
.请参阅:使用NaviationUI更新UI组件> AppBarConfigurationb.创建
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)}}
尝试的解决方案
-
使用
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
andFragmentContainerView
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 theBottomNavigationView
in the MainActivity.kt with aFragmentContainerView
.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
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 theAppBarConfiguration
.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' }
Create a menu for the
BottomNavigationView
, bottom_nav.xml, under app > res > menu.a. Add string values for the menu
id
andtitle
.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>
- Add the
FragmentContainerView
andBottomNavigationView
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>
Enable the
BottomNavigationView
in MainActivity.kt.a. Create
AppBarConfiguration
. See: Update UI components with NaviationUI > AppBarConfigurationb. Create the
NavHostFragment
andNavController
. See: StackOverflow solution for FragmentContainerView using findNavControllerc. 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
Create the
NavController
withfindNavController(R.id.nav_host_container)
as outlined in the documentation.Implement a
fragment
view instead ofFragmentContainerView
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屋!