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

异构RecyclerView条目动态加载未知数量EditText实现方案

动态未知数量EditText的RecyclerView适配方案

核心逻辑不需要提前定义多套异构布局,现有适配器基础逻辑完全不用改动,直接复用现有通用条目布局,在条目内置的parent_edittext垂直容器中,根据JSON返回的字段配置动态增减EditText即可,完全适配数量不固定的场景。

1. 补全数据模型,解决复用输入丢失问题

首先在自定义字段的数据类中增加输入内容存储字段,避免RecyclerView滚动复用的时候输入内容错乱、丢失:

data class DisplayCustomFields(
    // 以下字段替换为你JSON实际返回的字段属性即可
    val fieldId: Int, // 字段唯一标识
    val fieldLabel: String, // 字段名称
    val placeholder: String? = null, // 输入框提示文本
    var inputValue: String? = null // 存储用户输入内容,必须声明为var可变类型
)

2. 修改ViewHolder绑定逻辑,动态加载EditText

直接修改现有Base_DisplayViewHolder的bind方法,每次绑定条目时先清理容器内复用残留的旧控件,再根据当前条目的自定义字段数量逐个生成EditText加入容器,同时绑定文本监听实时存储输入内容:

class Base_DisplayViewHolder(
    private val itemBinding: ItemDisplayBinding,
    private val listener: Adapter_base_Display.Base_DisplayListener,
    private val activityIns: FragmentActivity,
    private var parent: ViewGroup,
    private val items: ArrayList<DisplaySections>,
) : RecyclerView.ViewHolder(itemBinding.root), View.OnClickListener {

    // 缓存当前绑定的条目数据、文本监听器,避免复用导致内容错乱、内存泄漏
    private var currentBoundItem: DisplaySections? = null
    private val textWatcherMap = hashMapOf<Int, TextWatcher>()

    init {
        itemBinding.root.setOnClickListener(this)
    }

    fun bind(item: DisplaySections) {
        currentBoundItem = item
        itemBinding.textView2.text = item.name

        val editTextContainer = itemBinding.parentEdittext
        // 清空容器内旧控件、移除旧监听器
        editTextContainer.removeAllViews()
        textWatcherMap.values.forEach { watcher ->
            // 遍历移除所有旧文本监听,防止内存泄漏
        }
        textWatcherMap.clear()

        // 遍历当前条目的自定义字段,逐个生成EditText
        item.displayCustomFields.forEach { customField ->
            // 加载你预定义的EditText布局,布局名替换成你项目里的实际文件名
            val editText = LayoutInflater.from(itemBinding.root.context)
                .inflate(R.layout.item_edittext_display, editTextContainer, false) as EditText

            // 配置EditText属性
            editText.hint = customField.placeholder ?: customField.fieldLabel
            editText.setText(customField.inputValue)
            editText.tag = customField.fieldId

            // 绑定文本输入监听,实时存输入内容到数据模型
            val watcher = object : TextWatcher {
                override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
                override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
                override fun afterTextChanged(s: Editable?) {
                    customField.inputValue = s?.toString()
                }
            }
            editText.addTextChangedListener(watcher)
            textWatcherMap[customField.fieldId] = watcher

            // 将配置好的EditText加入容器
            editTextContainer.addView(editText)
        }
    }

    override fun onClick(v: View?) {
        listener.onClickeddisplay(adapterPosition)
    }
}

注意:你贴出的条目基础布局缺少最外层根布局标签,记得补一个orientation为vertical的LinearLayout作为根容器,否则布局加载会报错。ViewBinding会自动把下划线命名的id转成驼峰,比如parent_edittext对应绑定类里的parentEdittext,和代码保持一致即可。

3. 性能优化(可选)

如果单条目的自定义字段数量较多(超过10个),可以不用每次绑定都全量删除重建EditText,改成简单的View缓存逻辑:

  • 容器内已有EditText数量多于需要展示的数量时,把多余的EditText设为GONE隐藏即可
  • 数量不足时再inflate新的EditText补入
  • 复用已有EditText时先移除旧的文本监听器,再绑定新的数据
    字段数量少的场景下全量删建完全不会有性能问题,不需要额外优化。

4. 输入内容获取

最终需要提交表单或者获取用户输入时,直接遍历适配器中存储的items列表即可,每个DisplaySections下displayCustomFields中的inputValue字段就是用户对应输入的内容,不需要遍历View查找取值。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 15:33:13