Android ViewPager恢复后自动跳转到首个Fragment问题求助
问题描述
我开发的Android应用包含5个Fragment,通过ViewPager作为容器展示,Activity中设有上一页、下一页按钮。正常操作时,点击下一页可顺利切换至最后一个Fragment;但点击Android系统后台按钮使最后一个Fragment进入暂停状态,再次恢复应用时,ViewPager会自动跳转到首个Fragment的初始位置,该问题需要解决。
相关代码
Activity中的ViewPager初始化代码
private fun setUpViewPager(){ val fragmentList : MutableList< Fragment> = mutableListOf() fragmentList.add(SurveyPageOneFragment.newInstance(false)) fragmentList.add(SurveyPageTwoFragment.newInstance(false)) fragmentList.add(SurveyPageThreeFragment.newInstance(false)) fragmentList.add(SurveyPageFourFragment.newInstance(false)) fragmentList.add(SurveyPageFiveFragment.newInstance(false)) surveyPagerAdapter = SurveyPagerAdapter(fragmentList,supportFragmentManager,lifecycle) binding.viewPager.adapter = surveyPagerAdapter binding.dotsIndicator.attachTo(binding.viewPager) }
Activity中的点击事件与页面监听代码
private fun setOnClick(){ binding.btnNext.setOnClickListener { if (binding.viewPager.currentItem < binding.viewPager.adapter?.itemCount!!){ when (fragPosition) { 0 -> { Log.i("TAG", "Page 1: Position $fragPosition") binding.viewPager.currentItem = binding.viewPager.currentItem +1 } 1 -> { Log.i("TAG", "Page 2: Position $fragPosition") binding.viewPager.currentItem = binding.viewPager.currentItem +1 } 2 -> { Log.i("TAG", "Page 3: Position $fragPosition") binding.viewPager.currentItem = binding.viewPager.currentItem +1 } 3 -> { Log.i("TAG", "Page 4: Position $fragPosition") binding.viewPager.currentItem = binding.viewPager.currentItem +1 } 4 -> { Log.i("TAG", "Page 5: Position $fragPosition") binding.viewPager.isUserInputEnabled = true binding.viewPager.currentItem = binding.viewPager.currentItem +1 } } } } binding.btnBack.setOnClickListener { if (binding.viewPager.currentItem != 0){ binding.viewPager.currentItem = binding.viewPager.currentItem -1 } } binding.btnDone.setOnClickListener { startActivity(Intent(context,SurveyCompleteActivity::class.java)) } val onPageChangeCallback = object : OnPageChangeCallback(){ override fun onPageSelected(position: Int) { Log.i("TAG", "PageChange: $position") fragPosition = position if (position == 0){ binding.btnBack.visibility = View.GONE }else{ binding.btnBack.visibility = View.VISIBLE } if (position < binding.viewPager.adapter?.itemCount!! -1){ binding.btnNext.visibility = View.VISIBLE binding.btnDone.visibility = View.GONE }else{ binding.btnNext.visibility = View.GONE binding.btnDone.visibility = View.VISIBLE binding.viewPager.isUserInputEnabled = false } } } binding.viewPager.registerOnPageChangeCallback(onPageChangeCallback) }
Fragment One代码
override fun onResume() { Log.i("TAG", "onResume: survey page one") super.onResume() viewLifecycleOwner.lifecycle.currentState === Lifecycle.State.RESUMED } override fun onPause() { Log.i("TAG", "onPause: survey page one") super.onPause() } override fun onDestroy() { super.onDestroy() _binding = null } companion object { @JvmStatic fun newInstance(isMyBoolean: Boolean) = SurveyPageOneFragment().apply { val fragment = SurveyPageOneFragment() arguments = Bundle().apply { putBoolean("REPLACE WITH A STRING CONSTANT", isMyBoolean) } fragment.arguments return fragment } }
Fragment Five代码
override fun onResume() { Log.i("TAG", "onResume: survey page five") super.onResume() viewLifecycleOwner.lifecycle.currentState === Lifecycle.State.RESUMED } override fun onPause() { Log.i("TAG", "onPause: survey page five") super.onPause() } override fun onDestroy() { super.onDestroy() _binding = null } companion object { @JvmStatic fun newInstance(isMyBoolean: Boolean) = SurveyPageFiveFragment().apply { val fragment = SurveyPageFiveFragment() arguments = Bundle().apply { putBoolean("REPLACE WITH A STRING CONSTANT", isMyBoolean) } fragment.arguments return fragment } }
解决方案
这个问题的核心是Activity销毁重建时没有保存和恢复ViewPager的当前页面位置。Android系统在应用退到后台时,可能因内存不足销毁Activity,再次进入时重建,此时ViewPager会回到初始位置。解决步骤如下:
- 保存当前页面位置
在Activity中重写onSaveInstanceState方法,保存ViewPager的当前索引:
override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putInt("CURRENT_PAGE_POSITION", binding.viewPager.currentItem) }
- 恢复页面位置
在Activity的onCreate方法中,恢复保存的页面位置,并同步更新按钮状态:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivitySurveyBinding.inflate(layoutInflater) setContentView(binding.root) setUpViewPager() setOnClick() savedInstanceState?.let { val savedPosition = it.getInt("CURRENT_PAGE_POSITION", 0) binding.viewPager.setCurrentItem(savedPosition, false) fragPosition = savedPosition updateButtonVisibility(savedPosition) } } // 抽取按钮状态更新逻辑,避免重复代码 private fun updateButtonVisibility(position: Int) { binding.btnBack.visibility = if (position == 0) View.GONE else View.VISIBLE if (position < binding.viewPager.adapter?.itemCount!! -1) { binding.btnNext.visibility = View.VISIBLE binding.btnDone.visibility = View.GONE } else { binding.btnNext.visibility = View.GONE binding.btnDone.visibility = View.VISIBLE binding.viewPager.isUserInputEnabled = false } }
- 优化Fragment的newInstance方法(可选但推荐)
当前Fragment的newInstance方法存在冗余代码,可简化为:
// Fragment One的newInstance简化版 companion object { private const val ARG_IS_BOOLEAN = "arg_is_boolean" @JvmStatic fun newInstance(isMyBoolean: Boolean) = SurveyPageOneFragment().apply { arguments = Bundle().apply { putBoolean(ARG_IS_BOOLEAN, isMyBoolean) } } }
用常量代替硬编码字符串,避免拼写错误,同时简化逻辑。
内容的提问来源于stack exchange,提问作者Rahul Rokade
相关产品推荐
相关产品推荐

