我正在尝试使用ViewPager实现BottomNavigation,以便在用户在底部导航片段之间切换时保存底部导航片段的状态和返回堆栈,我想出了以下解决方案:
class MainActivity : AppCompatActivity() {
private val autoFragment: RootFragment = RootFragment.newInstance(AutoFragment())
private val ordersFragment: RootFragment = RootFragment.newInstance(OrdersContainerFragment())
private val driversFragment: RootFragment = RootFragment.newInstance(DriversFragment())
private val infoFragment: RootFragment = RootFragment.newInstance(InfoContainerFragment())
private var selectedFragment: RootFragment = autoFragment
private var prevMenuItem: MenuItem? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupBottomNav()
setupViewPager()
}
private fun setupViewPager() {
nonSwipeableViewPager.adapter = FragmentAdapter(
supportFragmentManager, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
)
.apply {
add(autoFragment, getString(R.string.title_auto))
add(ordersFragment, getString(R.string.title_orders))
add(driversFragment, getString(R.string.title_drivers))
add(infoFragment, getString(R.string.title_info))
}
nonSwipeableViewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
override fun onPageScrollStateChanged(state: Int) {}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
override fun onPageSelected(position: Int) {
if (prevMenuItem != null) {
prevMenuItem!!.isChecked = false
} else {
bottomNav.menu.getItem(0).isChecked = false
}
bottomNav.menu.getItem(position).isChecked = true
prevMenuItem = bottomNav.menu.getItem(position)
}
})
nonSwipeableViewPager.offscreenPageLimit = 4
}
private fun setupBottomNav() {
bottomNav.setOnNavigationItemSelectedListener {
when (it.itemId) {
R.id.navigation_auto -> selectFragment(autoFragment, 0)
R.id.navigation_orders -> selectFragment(ordersFragment, 1)
R.id.navigation_drivers -> selectFragment(driversFragment, 2)
R.id.navigation_info -> selectFragment(infoFragment, 3)
else -> false
}
}
}
private fun selectFragment(fragment: RootFragment, fragmentIndex: Int): Boolean {
nonSwipeableViewPager.setCurrentItem(fragmentIndex, false)
if (selectedFragment == fragment) fragment.popToRoot()
selectedFragment = fragment
return true
}
}
class RootFragment : Fragment() {
private lateinit var fragment: Fragment
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
childFragmentManager.beginTransaction().replace(R.id.fragment_container, fragment).commit()
return inflater.inflate(R.layout.fragment_root, container, false)
}
fun popToRoot() {
for (i in 0 until childFragmentManager.backStackEntryCount) {
childFragmentManager.popBackStack()
}
}
companion object {
fun newInstance(fragment: Fragment) = RootFragment().apply {
this.fragment = fragment
}
}
}
但是有时当我离开应用程序然后尝试再次打开它时,会弹出此错误:
java.lang.RuntimeException: Unable to start activity ComponentInfo{kg.umarcargo.owner/kg.umarcargo.owner.MainActivity}: kotlin.UninitializedPropertyAccessException: lateinit property fragment has not been initialized
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2895)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1616)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:6651)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:824)
Caused by: kotlin.UninitializedPropertyAccessException: lateinit property fragment has not been initialized
at kg.umarcargo.owner.RootFragment.onCreateView(RootFragment.kt:20)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2698)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1356)
at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1434)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1497)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2625)
at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2577)
at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:247)
at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:541)
at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:201)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1335)
at android.app.Activity.performStart(Activity.java:7108)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2780)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2895)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1616)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:176)
at android.app.ActivityThread.main(ActivityThread.java:6651)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:824)
我的实现可能出了点问题。希望得到我的问题的答案和可能的解决方案。 另外,副作用之一是由于某些原因,当我按下“后退”按钮时,应用程序无法退出。如果您知道答案,请与我分享!