You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android底部导航栏实现报错:FragmentContainerView填充失败

问题描述

我是Android开发新手,尝试为应用实现可切换4个Fragment(首页、搜索、收藏、设置)的底部导航栏,但遇到XML相关报错,提示无法初始化FragmentContainerView。

报错核心信息

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.masala_food_recipes/com.example.masala_food_recipes.MainActivity}: android.view.InflateException: Binary XML file line #28 in com.example.masala_food_recipes:layout/activity_main: Binary XML file line #28 in com.example.masala_food_recipes:layout/activity_main: Error inflating class androidx.fragment.app.FragmentContainerView

相关代码

activity_main.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:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragment_container_view"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toTopOf="@+id/bottom_navigation"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/navigation" />


    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation"
        style="@style/bottomNavigationBackground"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingHorizontal="8dp"
        app:itemActiveIndicatorStyle="@style/Indicator"
        app:itemIconTint="@color/icon_color"
        app:itemPaddingBottom="16dp"
        app:itemPaddingTop="12dp"
        app:itemRippleColor="@color/light_orange"
        app:itemTextColor="@color/label_color"
        app:labelVisibilityMode="labeled"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:menu="@menu/bottom_navigation_menu" />

</androidx.constraintlayout.widget.ConstraintLayout>

activity_main.kt

package com.example.masala_food_recipes


import android.annotation.SuppressLint
import android.content.Context
import android.os.Bundle
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.navigation.NavController
import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.NavigationUI
import androidx.navigation.ui.setupWithNavController
import com.example.masala_food_recipes.data.DataManager
import com.example.masala_food_recipes.data.interactors.Cuisines
import com.example.masala_food_recipes.data.interactors.ForYouRecipe
import com.example.masala_food_recipes.data.interactors.SearchRecipe
import com.example.masala_food_recipes.data.interactors.UnderFiveIngredient
import com.example.masala_food_recipes.data.interactors.UnderTwentyMinRecipe
import com.example.masala_food_recipes.databinding.ActivityMainBinding
import com.example.masala_food_recipes.ui.fragment.FavouriteFragment
import com.example.masala_food_recipes.ui.fragment.HomeFragment
import com.example.masala_food_recipes.ui.fragment.SearchFragment
import com.example.masala_food_recipes.ui.fragment.SettingFragment

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    private lateinit var navController: NavController
    private lateinit var homeScreen: HomeFragment
    private val favouriteScreen = FavouriteFragment()
    private lateinit var searchScreen : SearchFragment
    private val settingScreen = SettingFragment()

    private val allRecipes by lazy { DataManager(this).getAllRecipesData() }
    private val under20MinList by lazy { UnderTwentyMinRecipe(allRecipes).execute() }
    private val under5IngredientList by lazy { UnderFiveIngredient(allRecipes).execute() }
    private val cuisineList by lazy { Cuisines(allRecipes).getCuisineCards() }
    private val forYouList by lazy { ForYouRecipe(allRecipes).execute() }
    private val searchList by lazy { SearchRecipe(allRecipes).execute() }

    @SuppressLint("SourceLockedOrientationActivity")
    override fun onCreate(savedInstanceState: Bundle?) {
        val sharedPref = this.getSharedPreferences("MY_PREFS", Context.MODE_PRIVATE)
        if (sharedPref.getBoolean("current_state", false)) {
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
        }
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        init()
    }

    private fun init() {
        homeScreen = HomeFragment(cuisineList, forYouList, under20MinList, under5IngredientList)
        searchScreen = SearchFragment(searchList)
        val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragment_container_view) as NavHostFragment
        navController = navHostFragment.navController
        binding.bottomNavigation.setupWithNavController(navController)
    }

    @Deprecated("Deprecated in Java")
    override fun onBackPressed() {
        val navController = findNavController(R.id.fragment_container_view)
        val currentFragmentId = navController.currentDestination?.id
        if (currentFragmentId == R.id.homeFragment) {
            val builder = AlertDialog.Builder(this)
            builder.setMessage("Are you sure you want to exit?").setCancelable(false)
                .setPositiveButton("Yes") { _, _ -> finish() }
                .setNegativeButton("No") { dialog, _ -> dialog.cancel() }
            val alert = builder.create()
            alert.show()
        }
        else navController.popBackStack()

    }
}

完整报错日志

Process: com.example.masala_food_recipes, PID: 18474
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.masala_food_recipes/com.example.masala_food_recipes.MainActivity}: android.view.InflateException: Binary XML file line #28 in com.example.masala_food_recipes:layout/activity_main: Binary XML file line #28 in com.example.masala_food_recipes:layout/activity_main: Error inflating class androidx.fragment.app.FragmentContainerView
解决方案

1. 移除冗余布局组件

布局中同时存在ViewPager2和NavHostFragment,两者都是Fragment容器,选其一即可。既然用Navigation组件实现底部导航,直接删除ViewPager2代码,修改后的activity_main.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:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragment_container_view"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toTopOf="@+id/bottom_navigation"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/navigation" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_navigation"
        style="@style/bottomNavigationBackground"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingHorizontal="8dp"
        app:itemActiveIndicatorStyle="@style/Indicator"
        app:itemIconTint="@color/icon_color"
        app:itemPaddingBottom="16dp"
        app:itemPaddingTop="12dp"
        app:itemRippleColor="@color/light_orange"
        app:itemTextColor="@color/label_color"
        app:labelVisibilityMode="labeled"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:menu="@menu/bottom_navigation_menu" />

</androidx.constraintlayout.widget.ConstraintLayout>

2. 删除手动实例化Fragment的代码

Navigation组件会自动根据导航图管理Fragment实例,手动创建的homeScreen、searchScreen等实例完全多余,还可能导致冲突。修改activity_main.kt,移除这些代码:

package com.example.masala_food_recipes


import android.annotation.SuppressLint
import android.content.Context
import android.os.Bundle
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.navigation.NavController
import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupWithNavController
import com.example.masala_food_recipes.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding
    private lateinit var navController: NavController

    @SuppressLint("SourceLockedOrientationActivity")
    override fun onCreate(savedInstanceState: Bundle?) {
        val sharedPref = this.getSharedPreferences("MY_PREFS", Context.MODE_PRIVATE)
        if (sharedPref.getBoolean("current_state", false)) {
            AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
        }
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        init()
    }

    private fun init() {
        val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragment_container_view) as NavHostFragment
        navController = navHostFragment.navController
        binding.bottomNavigation.setupWithNavController(navController)
    }

    @Deprecated("Deprecated in Java")
    override fun onBackPressed() {
        val currentFragmentId = navController.currentDestination?.id
        if (currentFragmentId == R.id.homeFragment) {
            val builder = AlertDialog.Builder(this)
            builder.setMessage("确定要退出吗?").setCancelable(false)
                .setPositiveButton("是") { _, _ -> finish() }
                .setNegativeButton("否") { dialog, _ -> dialog.cancel() }
            val alert = builder.create()
            alert.show()
        } else {
            navController.popBackStack()
        }
    }
}

3. 配置导航图与菜单对应关系

确保res/navigation/navigation.xml存在,并且里面的Fragment目的地ID和底部导航菜单res/menu/bottom_navigation_menu.xml的Item ID完全一致:

导航示例(navigation.xml)

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/navigation"
    app:startDestination="@id/homeFragment">

    <fragment
        android:id="@+id/homeFragment"
        android:name="com.example.masala_food_recipes.ui.fragment.HomeFragment"
        android:label="首页" />

    <fragment
        android:id="@+id/searchFragment"
        android:name="com.example.masala_food_recipes.ui.fragment.SearchFragment"
        android:label="搜索" />

    <fragment
        android:id="@+id/favouriteFragment"
        android:name="com.example.masala_food_recipes.ui.fragment.FavouriteFragment"
        android:label="收藏" />

    <fragment
        android:id="@+id/settingFragment"
        android:name="com.example.masala_food_recipes.ui.fragment.SettingFragment"
        android:label="设置" />
</navigation>

底部菜单示例(bottom_navigation_menu.xml)

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/homeFragment"
        android:icon="@drawable/ic_home"
        android:title="首页" />
    <item
        android:id="@+id/searchFragment"
        android:icon="@drawable/ic_search"
        android:title="搜索" />
    <item
        android:id="@+id/favouriteFragment"
        android:icon="@drawable/ic_favourite"
        android:title="收藏" />
    <item
        android:id="@+id/settingFragment"
        android:icon="@drawable/ic_setting"
        android:title="设置" />
</menu>

4. 用ViewModel传递数据

原来手动给Fragment传参的方式不符合Navigation规范,改用ViewModel统一管理数据:

创建RecipeViewModel

import androidx.lifecycle.ViewModel
import com.example.masala_food_recipes.data.DataManager
import com.example.masala_food_recipes.data.interactors.*

class RecipeViewModel(private val context: android.content.Context) : ViewModel() {
    val allRecipes by lazy { DataManager(context).getAllRecipesData() }
    val under20MinList by lazy { UnderTwentyMinRecipe(allRecipes).execute() }
    val under5IngredientList by lazy { UnderFiveIngredient(allRecipes).execute() }
    val cuisineList by lazy { Cuisines(allRecipes).getCuisineCards() }
    val forYouList by lazy { ForYouRecipe(allRecipes).execute() }
    val searchList by lazy { SearchRecipe(allRecipes).execute() }
}

在Fragment中获取ViewModel

以HomeFragment为例:

import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModels

class HomeFragment : Fragment() {
    private val viewModel: RecipeViewModel by viewModels {
        object : ViewModelProvider.Factory {
            override fun <T : ViewModel> create(modelClass: Class<T>): T {
                return RecipeViewModel(requireContext()) as T
            }
        }
    }

    override fun onViewCreated(view: android.view.View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // 使用viewModel.cuisineList、viewModel.forYouList等数据
    }
}

完成以上修改后,重新构建项目即可解决报错,底部导航栏就能正常切换四个Fragment了。

内容的提问来源于stack exchange,提问作者Zeyad Galal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 15:48:09