У меня есть одно действие и несколько фрагментов. Я настроил свою активность с помощью NavController
и навигационного графика следующим образом:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val navHostFragment = supportFragmentManager
.findFragmentById(R.id.nav_host_activity_main) as NavHostFragment
navController = navHostFragment.findNavController()
}
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp() || super.onSupportNavigateUp()
}
В этом навигационном графе я позабочусь о заставке, входе в систему, фрагменте регистрации и переходе к основному фрагменту, который имеет BottomNavigationView
с двумя подфрагментами.
Я сделал меню для фрагментов нижнего NavView и построил для них график, идентификатор меню совпадает с идентификатором нижнего навигационного графика.
Мой макет выглядит так:
<androidx.fragment.app.FragmentContainerView
android:id = "@+id/nav_host_fragment_main"
android:name = "androidx.navigation.fragment.NavHostFragment"
android:layout_width = "0dp"
android:layout_height = "0dp"
app:defaultNavHost = "true"
app:layout_constraintBottom_toTopOf = "@+id/bottom_Navigation_view"
app:layout_constraintEnd_toEndOf = "parent"
app:layout_constraintStart_toStartOf = "parent"
app:layout_constraintTop_toTopOf = "parent"
app:navGraph = "@navigation/bottom_view_nav_graph" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id = "@+id/bottom_Navigation_view"
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:background = "@color/white"
app:layout_constraintBottom_toBottomOf = "parent"
app:layout_constraintEnd_toEndOf = "parent"
app:layout_constraintStart_toStartOf = "parent"
app:menu = "@menu/bottom_nav_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>
В основном фрагменте я пытаюсь настроить нижний навигационный вид с навигационным графиком следующим образом:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val appCompat = requireActivity() as AppCompatActivity
val navHostFragment = appCompat.supportFragmentManager.findFragmentById(R.id.nav_host_fragment_main) as NavHostFragment
val navController = navHostFragment.findNavController()
binding.bottomNavigationView.setupWithNavController(navController)
}
Однако я продолжаю получать это исключение:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.ak.chatter, PID: 1937
java.lang.NullPointerException: null cannot be cast to non-null type androidx.navigation.fragment.NavHostFragment
at com.ak.chatter.ui.main.MainFragment.onViewCreated(MainFragment.kt:34)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:332)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
at androidx.fragment.app.FragmentManager.addAddedFragments(FragmentManager.java:2224)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1997)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1953)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
at androidx.fragment.app.FragmentManager$4.run(FragmentManager.java:413)
at android.os.Handler.handleCallback(Handler.java:900)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:219)
at android.app.ActivityThread.main(ActivityThread.java:8347)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055)
Нет, общий макет — это макет основного фрагмента
java.lang.NullPointerException: null cannot be cast to non-null type
androidx.navigation.fragment.NavHostFragment
Вы пытаетесь преобразовать нулевое значение в ненулевое.
null
получается из оператора appCompat.supportFragmentManager.findFragmentById(R.id.nav_host_fragment_main)
.
Потому что supportFragmentManager
используется в качестве диспетчера фрагментов, которые размещены во фрагменте. Хотя supportFragmentManager
должен управлять фрагментами, размещенными в активности.
Принимая во внимание, что вместо этого следует использовать childFragmentManager
для управления фрагментами, размещенными в другом фрагменте.
Итак, чтобы решить эту проблему, замените supportFragmentManager
на childFragmentManager
в основном классе фрагментов:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val appCompat = requireActivity() as AppCompatActivity
val navHostFragment = appCompat.childFragmentManager.findFragmentById(R.id.nav_host_fragment_main) as NavHostFragment
val navController = navHostFragment.findNavController()
binding.bottomNavigationView.setupWithNavController(navController)
}
для меня childFragmentManager получается из фрагмента, а не из appCompat
общий макет предназначен для активности, верно?