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

Android开发:能否在表单中用RecyclerView实现多季添加?

解决方案:用RecyclerView实现动态添加季表单

完全可以用RecyclerView实现这个需求,这是处理动态表单条目的理想方案,既能复用布局,也能灵活管理任意数量的季输入项。下面是针对你的问题的具体修改步骤:

一、重构AddSeasonAdapter

核心思路是用数据列表替代原来的seasonsCount,通过维护列表来管理所有季的输入数据,并提供添加条目和获取数据的方法:

class AddSeasonAdapter(private val layoutId: Int) : RecyclerView.Adapter<AddSeasonAdapter.ViewHolder>() {
    // 存储所有季的输入数据,用MutableList支持动态增删
    private val seasons = mutableListOf<SeasonModel>()

    // ViewHolder绑定item布局中的输入控件
    inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        // 替换成你item_add_season布局中实际的EditText ID
        val seasonNumberEt: EditText = view.findViewById(R.id.season_number_input)
        val episodeCountEt: EditText = view.findViewById(R.id.episode_count_input)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(layoutId, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val currentSeason = seasons[position]
        // 将数据绑定到输入框
        holder.seasonNumberEt.setText(currentSeason.number.toString())
        holder.episodeCountEt.setText(currentSeason.episodeCount.toString())

        // 监听输入变化,实时更新列表中的数据
        holder.seasonNumberEt.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                s?.toString()?.toIntOrNull()?.let {
                    seasons[position] = currentSeason.copy(number = it)
                }
            }
            override fun afterTextChanged(s: Editable?) {}
        })

        holder.episodeCountEt.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                s?.toString()?.toIntOrNull()?.let {
                    seasons[position] = currentSeason.copy(episodeCount = it)
                }
            }
            override fun afterTextChanged(s: Editable?) {}
        })
    }

    override fun getItemCount(): Int = seasons.size

    // 对外提供添加新季条目的方法
    fun addSeason() {
        // 初始化一个空的SeasonModel(根据你的Model结构调整构造参数)
        seasons.add(SeasonModel(number = 0, episodeCount = 0))
        // 通知RecyclerView插入新条目
        notifyItemInserted(seasons.size - 1)
    }

    // 对外提供获取所有有效季数据的方法(过滤未输入的无效项)
    fun getValidSeasons(): List<SeasonModel> {
        return seasons.filter { it.number > 0 && it.episodeCount > 0 }
    }
}

说明:

  • 假设你的SeasonModel是data class(自动生成copy方法),如果不是,需要手动实现数据更新逻辑。
  • 替换代码中的EditText ID为你item_add_season布局中实际的控件ID。

二、修改AddShowActivity

持有适配器实例,实现添加按钮逻辑和表单提交逻辑:

class AddShowActivity : AppCompatActivity() {
    private lateinit var editTextName: EditText
    private lateinit var editTextNote: EditText
    private lateinit var confirmButton: Button
    private lateinit var addSeasonButton: Button
    private lateinit var seasonsRecyclerView: RecyclerView
    // 持有适配器实例,方便调用方法
    private lateinit var seasonAdapter: AddSeasonAdapter

    @SuppressLint("NewApi")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_add_show)
        
        editTextName = findViewById(R.id.name_input)
        editTextNote = findViewById(R.id.note_input)

        // 初始化适配器并绑定到RecyclerView
        seasonAdapter = AddSeasonAdapter(R.layout.item_add_season)
        seasonsRecyclerView = findViewById(R.id.seasons_recycler_view)
        seasonsRecyclerView.adapter = seasonAdapter
        seasonsRecyclerView.layoutManager = LinearLayoutManager(this)

        // 初始添加一个季条目,避免用户首次点击Add Season
        seasonAdapter.addSeason()

        confirmButton = findViewById(R.id.confirm_button)
        confirmButton.setOnClickListener{
            sendForm()
        }

        addSeasonButton = findViewById(R.id.add_season_button)
        addSeasonButton.setOnClickListener {
            seasonAdapter.addSeason()
            // 滚动到新添加的条目,提升用户体验
            seasonsRecyclerView.scrollToPosition(seasonAdapter.itemCount - 1)
        }
    }

    @SuppressLint("NewApi")
    private fun sendForm(){
        val repo = ShowRepository()
        val showName = editTextName.text.toString().trim()
        // 修正:备注应该是String类型,你原来的parseInt是错误的
        val showNote = editTextNote.text.toString().trim()

        // 获取适配器中的有效季数据
        val seasonsList = seasonAdapter.getValidSeasons()

        // 表单验证
        if (showName.isEmpty()) {
            Toast.makeText(this, "请输入剧集名称", Toast.LENGTH_SHORT).show()
            return
        }
        if (seasonsList.isEmpty()) {
            Toast.makeText(this, "请至少添加一个有效季(季数和集数需大于0)", Toast.LENGTH_SHORT).show()
            return
        }

        val show = ShowModel(UUID.randomUUID().toString(), showName, showNote, seasonsList)
        repo.insertShow(show)
        finish()
    }
}

说明:

  • 修正了showNote的类型错误(从parseInt改为toString),因为备注应该是文本而非数字。
  • 添加了基础表单验证,避免空数据存入。
  • 初始添加一个季条目,优化用户首次使用体验。

三、关键问题解答

  1. 如何向RecyclerView添加新条目?
    通过调用适配器的addSeason()方法,向数据列表中添加新的SeasonModel,然后用notifyItemInserted()通知RecyclerView更新,这样只会刷新新增的条目,性能更优。

  2. 如何从适配器外部获取输入数据?
    在适配器中定义getValidSeasons()方法,返回过滤后的有效季数据,Activity直接调用该方法即可获取所有用户输入的季信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 19:01:20