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

Android嵌套RecyclerView获取所有输入框内容仅返回最后项如何解决

核心问题

你拿不到第一个父项内容的根本原因是MainAdapter里的parentItemHolder和childAdapter被声明为全局变量,每次onBindViewHolder绑定新的父项时,这两个变量都会被覆盖成当前父项的实例,最终只会保留最后一个父项的相关引用,所以读取时只能拿到最后一个父项的4条数据。

除此之外还有几个常见错误:

  • 没有为每个父项单独保存对应的子Adapter实例,遍历所有父项时找不到对应子列表的入口
  • 没有给子项的EditText加文本变化监听,用户输入的内容不会同步到子Adapter的数据集里,直接读View很容易因为RecyclerView复用逻辑拿到错误内容
  • 读取数据时直接遍历ViewHolder,超出屏幕的ViewHolder会被回收,拿不到不可见区域的输入内容

修改方案

1. 改造MainAdapter,保存每个父项的子Adapter

class MainAdapter(var locationList: ArrayList<HashMap<String, String>>): 
RecyclerView.Adapter<MainAdapter.ViewHolder>() {

    val byDates = locationList.groupBy { it["time"] }
    // 用列表保存每个父位置对应的子Adapter
    private val childAdapters = mutableListOf<PropertyAdapter>()

    @SuppressLint("WrongConstant")
    override fun onBindViewHolder(holder: MainAdapter.ViewHolder, position: Int) {
        val sdf = SimpleDateFormat("MM/dd/yyyy")
        val dateList = byDates.values.toMutableList()
        holder.date?.text = sdf.format(dateList[position][0].get("time")?.toLong())
        holder.childRv?.layoutManager = LinearLayoutManager(holder.childRv.context, LinearLayout.VERTICAL, false)
        
        // 每个父项单独维护自己的子数据集
        val properyDataList:ArrayList<propertyDataClass> = ArrayList()
        val childAdapter = PropertyAdapter(properyDataList)
        holder.childRv.adapter = childAdapter
        // 把当前父项的子Adapter存入列表
        if (position >= childAdapters.size) {
            childAdapters.add(childAdapter)
        } else {
            childAdapters[position] = childAdapter
        }

        holder.date?.setOnClickListener(View.OnClickListener {
            properyDataList.add(propertyDataClass())
            childAdapter.notifyDataSetChanged()
        })
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainAdapter.ViewHolder {
        val v = LayoutInflater.from(parent.context).inflate(R.layout.recyclerview_item_dates, parent, false)
        return ViewHolder(v)
    }

    override fun getItemCount(): Int {
        return byDates.count()
    }

    class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
        val date = itemView.findViewById<TextView>(R.id.locationDate)
        val childRv = itemView.findViewById<RecyclerView>(R.id.childList)
    }

    fun getAllItemDetails():ArrayList<String>{
        val stringList = ArrayList<String>()
        try {
            // 遍历所有父项的子Adapter
            childAdapters.forEach { childAdapter ->
                // 调用子Adapter的方法拿所有输入内容
                val childValues = childAdapter.getAllItemValues()
                stringList.addAll(childValues)
            }
        }catch (e:Exception){
            e.printStackTrace()
        }
        return stringList
    }
}

2. 改造PropertyAdapter,同步输入内容到数据集

class PropertyAdapter(
    val propertyList: ArrayList<propertyDataClass>,
): RecyclerView.Adapter<PropertyAdapter.ViewHolder>() {

    override fun onBindViewHolder(holder: PropertyAdapter.ViewHolder, position: Int) {
        val propertyItem = propertyList[position]
        holder.etLabel?.text = propertyItem.inputName
        holder.etValue?.setText(propertyItem.inputValue)
        
        // 移除之前的监听避免复用冲突
        holder.etValue?.removeTextChangedListener(holder.textWatcher)
        // 给输入框加监听,内容变化实时更新到数据集
        holder.textWatcher = 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?) {
                propertyItem.inputValue = s?.toString() ?: ""
            }
        }
        holder.etValue?.addTextChangedListener(holder.textWatcher)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PropertyAdapter.ViewHolder {
        val v = LayoutInflater.from(parent.context).inflate(R.layout.recyclerview_item_locations, parent, false)
        return ViewHolder(v)
    }

    override fun getItemCount(): Int {
        return propertyList.size
    }

    class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
        val etLabel = itemView.findViewById<TextView>(R.id.etLabel)
        val etValue = itemView.findViewById<EditText>(R.id.etValue)
        // 保存当前item的文本监听实例,避免复用冲突
        var textWatcher: TextWatcher? = null
    }

    // 新增方法返回所有子项的输入值
    fun getAllItemValues(): List<String> {
        return propertyList.map { it.inputValue }
    }
}

修改后点击MainActivity的TextView即可拿到所有父项+子项的全部输入内容。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 20:57:05