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

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会回到初始位置。解决步骤如下:

  1. 保存当前页面位置
    在Activity中重写onSaveInstanceState方法,保存ViewPager的当前索引:
override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    outState.putInt("CURRENT_PAGE_POSITION", binding.viewPager.currentItem)
}
  1. 恢复页面位置
    在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
    }
}
  1. 优化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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 05:25:02