空 NavHostFragment/NavController 与 FragmentContainerView

Ada*_*itz 5 android android-fragments android-navigation android-architecture-navigation android-bottomappbar

预期的

\n\n

使用导航 UI 创建底部应用程序栏导航BottomNavigationViewFragmentContainerView类似于示例应用程序NavigationAdvancedSample

\n\n

请注意,NavigationAndvancedSample应用程序似乎没有使用文档中描述的相同实现,因为它有一个使用自定义扩展方法的解决方法实现setupWithNavController

\n\n

观察到的

\n\n

使用.在MainActivity.ktNavHostFragment中创建 时为 Null 。BottomNavigationViewFragmentContainerView

\n\n

可重现的错误和完整的代码示例可在BottomNavigationViewSample存储库中找到。

\n\n

错误

\n\n
\n

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

\n
\n\n

执行

\n\n
    \n
  1. 为第一个视图home.xml创建导航图,以显示在app > res > navigationBottomNavigationView下。

    \n\n

    A。当提示添加项目依赖项时,选择“确定”

    \n\n

    b. 添加kotlinOptions { jvmTarget = \'1.8\' }build.gradle (:someAppModule)以启用AppBarConfiguration.

    \n\n

    C。将片段添加到home.xml以显示在BottomNavigationView.

  2. \n
\n\n

主页.xml

\n\n
<?xml version="1.0" encoding="utf-8"?>\n<navigation xmlns:android="http://schemas.android.com/apk/res/android"\n    xmlns:app="http://schemas.android.com/apk/res-auto"\n    xmlns:tools="http://schemas.android.com/tools"\n    android:id="@+id/home"\n    app:startDestination="@id/homeFragment">\n\n    <fragment\n        android:id="@+id/homeFragment"\n        android:name="com.example.bottomnavigationviewsample.HomeFragment"\n        android:label="fragment_home"\n        tools:layout="@layout/fragment_home" />\n</navigation>\n
Run Code Online (Sandbox Code Playgroud)\n\n

构建.gradle

\n\n
apply plugin: \'com.android.application\'\napply plugin: \'kotlin-android\'\napply plugin: \'kotlin-android-extensions\'\n\nandroid {\n    compileSdkVersion 29\n    buildToolsVersion "29.0.3"\n\n    kotlinOptions { jvmTarget = \'1.8\' }\n\n    defaultConfig {\n        applicationId "com.example.bottomnavigationviewsample"\n        minSdkVersion 21\n        targetSdkVersion 29\n        versionCode 1\n        versionName "1.0"\n\n        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"\n    }\n\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile(\'proguard-android-optimize.txt\'), \'proguard-rules.pro\'\n        }\n    }\n\n}\n\ndependencies {\n    implementation fileTree(dir: \'libs\', include: [\'*.jar\'])\n    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"\n    implementation \'androidx.appcompat:appcompat:1.1.0\'\n    implementation \'androidx.core:core-ktx:1.2.0\'\n    implementation \'androidx.constraintlayout:constraintlayout:1.1.3\'\n    testImplementation \'junit:junit:4.12\'\n    androidTestImplementation \'androidx.test.ext:junit:1.1.1\'\n    androidTestImplementation \'androidx.test.espresso:espresso-core:3.2.0\'\n    implementation \'androidx.navigation:navigation-fragment-ktx:2.2.2\'\n    implementation \'androidx.navigation:navigation-ui-ktx:2.2.2\'\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n\n
    \n
  1. 在app > res > menu下为bottom_nav.xml创建BottomNavigationView一个菜单。

    \n\n

    A。添加菜单id和的字符串值title

    \n\n

    b. 为菜单添加矢量绘图icon

  2. \n
\n\n

底部导航.xml

\n\n
<?xml version="1.0" encoding="utf-8"?>\n<menu xmlns:android="http://schemas.android.com/apk/res/android">\n        <item\n            android:id="@+id/home"\n            android:icon="@drawable/ic_home_black_24dp"\n            android:contentDescription="@string/cd_home"\n            android:title="@string/title_home" />\n</menu>\n
Run Code Online (Sandbox Code Playgroud)\n\n
    \n
  1. FragmentContainerView将和添加BottomNavigationViewMainActivity.ktActivity_main.xml布局中。
  2. \n
\n\n

活动主文件

\n\n
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"\n    xmlns:app="http://schemas.android.com/apk/res-auto"\n    xmlns:tools="http://schemas.android.com/tools"\n    android:layout_width="match_parent"\n    android:layout_height="match_parent"\n    android:orientation="vertical"\n    tools:context=".MainActivity">\n\n    <androidx.fragment.app.FragmentContainerView\n        android:id="@+id/nav_host_container"\n        android:layout_width="match_parent"\n        android:layout_height="0dp"\n        android:layout_weight="1" />\n\n    <com.google.android.material.bottomnavigation.BottomNavigationView\n        android:id="@+id/bottom_nav"\n        android:layout_width="match_parent"\n        android:layout_height="wrap_content"\n        app:menu="@menu/bottom_nav"/>\n</LinearLayout>\n
Run Code Online (Sandbox Code Playgroud)\n\n
    \n
  1. BottomNavigationViewMainActivity.kt中启用。

    \n\n

    A。创造AppBarConfiguration请参阅:使用 NaviationUI > AppBarConfiguration更新 UI 组件

    \n\n

    b. 创建NavHostFragmentNavController请参阅:使用 findNavController 的 FragmentContainerView的 StackOverflow 解决方案

    \n\n

    C。设置操作栏导航。

    \n\n

    d. 设置BottomNavigationView导航。请参阅:使用 NavigationUI >底部导航更新 UI 组件

  2. \n
\n\n

MainActivity.kt

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

尝试的解决方案

\n\n
    \n
  1. 按照文档中的概述创建NavControllerwith 。findNavController(R.id.nav_host_container)

  2. \n
  3. 实现一个fragment视图而不是FragmentContainerViewActivity_main.xml中。

  4. \n
\n\n

活动主文件

\n\n
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"\n    xmlns:app="http://schemas.android.com/apk/res-auto"\n    xmlns:tools="http://schemas.android.com/tools"\n    android:layout_width="match_parent"\n    android:layout_height="match_parent"\n    android:orientation="vertical"\n    tools:context=".MainActivity">\n\n    <fragment\n        android:id="@+id/nav_host_container"\n        android:layout_width="match_parent"\n        android:layout_height="0dp"\n        android:layout_weight="1" />\n\n    <com.google.android.material.bottomnavigation.BottomNavigationView\n        android:id="@+id/bottom_nav"\n        android:layout_width="match_parent"\n        android:layout_height="wrap_content"\n        app:menu="@menu/bottom_nav"/>\n</LinearLayout>\n
Run Code Online (Sandbox Code Playgroud)\n

Ada*_*itz 2

为菜单项添加父导航图BottomNavigationView

完整的示例代码包含在BottomNavigationSample中。

  1. 为菜单片段创建父级导航图。请注意,这没有反映在NavigationAdvancedSample架构模式中,该架构模式具有三个独立的导航图,没有父导航图。

这可以通过每个菜单项的一个父导航图和片段或嵌套导航图来完成。嵌套导航图很好,因为每个子流都可以在嵌套图中组织。

主文件

<?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"
    android:id="@+id/main"
    app:startDestination="@id/home">
    <include app:graph="@navigation/home" />
    <include app:graph="@navigation/saved" />
</navigation>
Run Code Online (Sandbox Code Playgroud)
  1. navGraph添加使用在 中的父图FragmentContainerView

活动主文件

<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:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        app:defaultNavHost="true"
        app:navGraph="@navigation/main"/>

    <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>
Run Code Online (Sandbox Code Playgroud)
  1. BottomNavigationViewMainActivity.kt中启用。
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, R.id.saved))

        val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_container) as NavHostFragment
        val navController = navHostFragment.navController

        setupActionBarWithNavController(navController, appBarConfiguration)
        bottom_nav.setupWithNavController(navController)
    }
}
Run Code Online (Sandbox Code Playgroud)