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
相关产品推荐
相关产品推荐

