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

Android屏幕旋转时ScrollView滚动位置未保存,求故障原因

问题原因及修复方案

核心问题1:滚动位置的存取Key不匹配

在onSaveInstanceState中保存滚动位置用的Key是**"scrollposition"(小写字母p),但在onCreate中读取时用的是"scrollPosition"**(大写字母P)。Bundle对Key区分大小写,导致读取不到正确的滚动位置值,自然无法恢复。

核心问题2:viewsCount的逻辑完全错误

你的addTextView函数里,把viewsCount赋值为随机数(viewsCount = rand(1..100)),但这个变量本该用来记录添加的TextView数量。屏幕旋转恢复时,你用这个随机数循环添加TextView,导致恢复后的布局内容数量和旋转前完全不一致——比如原来只加了1个,恢复时可能加了50个,ScrollView的整体高度变了,就算滚动位置数值正确,也对应不上原来的位置。

修复后的完整代码

class MainActivity : AppCompatActivity() {
    private var viewsCount = 0 // 专门记录添加的TextView数量,不再存随机数

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        if (savedInstanceState != null){
            // 统一使用大写P的Key读取滚动位置
            val scrollPosition = savedInstanceState.getInt("scrollPosition")
            val scrollView = findViewById<ScrollView>(R.id.scrollView)
            scrollView.post { scrollView.scrollTo(0, scrollPosition) }
            
            viewsCount = savedInstanceState.getInt("viewsCount")
            val container = findViewById<LinearLayout>(R.id.innerConteiner)
            // 循环恢复每个TextView的内容
            for (i in 0 until viewsCount) {
                val text = savedInstanceState.getString("text_$i")
                val textView = TextView(this)
                textView.text = text
                textView.textSize = 20f
                container.addView(textView)
            }
        }
    }

    fun buttonAddClick(view: View) {
        addTextView()
    }

    private fun addTextView() {
        val randomNum = rand(1..100) // 单独存储每次生成的随机数
        val textView = TextView(this)
        textView.text = randomNum.toString()
        textView.textSize = 20f
        findViewById<LinearLayout>(R.id.innerConteiner).addView(textView)
        viewsCount++ // 每次添加后数量加1
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        outState.putInt("viewsCount", viewsCount)
        // 统一使用大写P的Key保存滚动位置
        outState.putInt("scrollPosition", findViewById<ScrollView>(R.id.scrollView).scrollY)
        
        // 额外保存每个TextView的文本内容,确保旋转后数字和之前一致
        val container = findViewById<LinearLayout>(R.id.innerConteiner)
        for (i in 0 until container.childCount) {
            val textView = container.getChildAt(i) as TextView
            outState.putString("text_$i", textView.text.toString())
        }
    }

    private fun rand(range: IntRange): Int {
        require(range.first <= range.last) { "Illegal Argument" }
        return Random(System.nanoTime()).nextInt(range) + range.first
    }
}

补充说明

原代码还有一个隐藏问题:只保存了viewsCount,但没保存每个TextView的具体随机数值,导致恢复时生成的是新的随机数,和旋转前的数字不一致。修复后的代码新增了保存每个TextView文本的逻辑,这样旋转后不仅滚动位置正确,显示的数字也和之前完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 03:43:18