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

设备旋转后重复引入的EditText填充相同数据问题求助

解决多次include布局后EditText旋转状态重复的问题

问题根源

Android在配置变更(如屏幕旋转)时,会通过onSaveInstanceState自动保存View状态,核心依据是View的id。当你用<include>多次引入同一布局时,布局内的EditText会共享相同的id,系统恢复状态时会将第一个EditText的内容覆盖到所有同id的控件上,导致数据串位。

最优解决方案推荐

方案一:自定义View封装重复布局(现代Android开发首选)

将包含EditText的重复布局封装成自定义View,让每个实例独立管理自身状态,从根源避免id冲突,同时保持XML整洁。

  1. 创建自定义View类
class UserInfoView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {

    private val binding = UserInfoLayoutBinding.inflate(LayoutInflater.from(context), this, true)

    // 提供字段的读写方法
    fun getFirstName(): String = binding.etFirstName.text.toString()
    fun setFirstName(name: String) { binding.etFirstName.setText(name) }

    fun getLastName(): String = binding.etLastName.text.toString()
    fun setLastName(name: String) { binding.etLastName.setText(name) }

    fun getCity(): String = binding.etCity.text.toString()
    fun setCity(city: String) { binding.etCity.setText(city) }

    // 重写状态保存与恢复方法,实现独立状态管理
    override fun onSaveInstanceState(): Parcelable? {
        val superState = super.onSaveInstanceState()
        val bundle = Bundle().apply {
            putString("first_name", getFirstName())
            putString("last_name", getLastName())
            putString("city", getCity())
            putParcelable("super_state", superState)
        }
        return bundle
    }

    override fun onRestoreInstanceState(state: Parcelable?) {
        var localState = state
        if (localState is Bundle) {
            setFirstName(localState.getString("first_name", ""))
            setLastName(localState.getString("last_name", ""))
            setCity(localState.getString("city", ""))
            localState = localState.getParcelable("super_state")
        }
        super.onRestoreInstanceState(localState)
    }
}
  1. 主布局中使用自定义View
<com.yourpackage.UserInfoView
    android:id="@+id/user_info1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

<com.yourpackage.UserInfoView
    android:id="@+id/user_info2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

每个自定义View实例会独立保存和恢复自身状态,完全避免id冲突问题,同时符合组件化开发思想,代码可复用性更高。

方案二:通过include标签ID手动管理状态

如果不想封装自定义View,可以给每个<include>设置唯一ID,然后在代码中通过include的根布局定位EditText,手动保存和恢复状态。

  1. 主布局设置include的唯一ID
<include
    android:id="@+id/include_user1"
    layout="@layout/user_info_layout" />

<include
    android:id="@+id/include_user2"
    layout="@layout/user_info_layout" />
  1. 代码中手动处理状态
override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    // 保存第一个用户的字段
    findViewById<View>(R.id.include_user1).run {
        outState.putString("user1_first", findViewById<EditText>(R.id.et_first_name).text.toString())
        outState.putString("user1_last", findViewById<EditText>(R.id.et_last_name).text.toString())
        outState.putString("user1_city", findViewById<EditText>(R.id.et_city).text.toString())
    }
    // 保存第二个用户的字段
    findViewById<View>(R.id.include_user2).run {
        outState.putString("user2_first", findViewById<EditText>(R.id.et_first_name).text.toString())
        outState.putString("user2_last", findViewById<EditText>(R.id.et_last_name).text.toString())
        outState.putString("user2_city", findViewById<EditText>(R.id.et_city).text.toString())
    }
}

override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)
    // 恢复第一个用户的字段
    findViewById<View>(R.id.include_user1).run {
        findViewById<EditText>(R.id.et_first_name).setText(savedInstanceState.getString("user1_first", ""))
        findViewById<EditText>(R.id.et_last_name).setText(savedInstanceState.getString("user1_last", ""))
        findViewById<EditText>(R.id.et_city).setText(savedInstanceState.getString("user1_city", ""))
    }
    // 恢复第二个用户的字段
    findViewById<View>(R.id.include_user2).run {
        findViewById<EditText>(R.id.et_first_name).setText(savedInstanceState.getString("user2_first", ""))
        findViewById<EditText>(R.id.et_last_name).setText(savedInstanceState.getString("user2_last", ""))
        findViewById<EditText>(R.id.et_city).setText(savedInstanceState.getString("user2_city", ""))
    }
}

这种方法无需修改原有布局结构,但代码量相对较多,适合快速适配现有项目。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 01:00:11