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

如何实现RecyclerView选中项的卡路里数值求和功能?

实现RecyclerView项CheckBox勾选时累加卡路里总和的逻辑改造方案

一、改造AdapterItem类

需要在Adapter中处理CheckBox的选中状态,同时通过回调将选中事件传递给Fragment,具体修改如下:

  1. 添加ViewHolder的CheckBox引用
    在ViewHolder中初始化CheckBox组件:
class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
    var numeLista: TextView = itemView.findViewById(R.id.numeLista)
    var caloriiLista: TextView = itemView.findViewById(R.id.caloriiLista)
    var checkBox: CheckBox = itemView.findViewById(R.id.checkbox) // 新增CheckBox引用
}
  1. 维护选中状态集合与回调接口
    在Adapter中添加选中项的集合(避免RecyclerView滚动时选中状态丢失),同时定义回调接口将选中事件通知给Fragment:
class AdapterItem(
    val userList: List<MyDataItem>,
    private val onCheckChanged: (Int, Boolean) -> Unit // 回调:参数为卡路里数值、是否选中
) : RecyclerView.Adapter<AdapterItem.ViewHolder>() {

    private val selectedPositions = mutableSetOf<Int>() // 保存选中项的position

    // ... 原有ViewHolder代码 ...

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = userList[position].foodItems[0]
        holder.numeLista.text = item.foodName
        holder.caloriiLista.text = item.calories.toString()
        
        // 恢复CheckBox选中状态,解决滚动时状态错乱问题
        holder.checkBox.isChecked = selectedPositions.contains(position)
        
        // 设置CheckBox点击监听
        holder.checkBox.setOnCheckedChangeListener { _, isChecked ->
            if (isChecked) {
                selectedPositions.add(position)
                onCheckChanged(item.calories, true)
            } else {
                selectedPositions.remove(position)
                onCheckChanged(item.calories, false)
            }
        }
    }

    // ... 原有getItemCount代码 ...
}

二、改造InformationFragment类

在Fragment中维护总卡路里变量,接收Adapter的回调并更新总和,同时将结果显示到界面上:

  1. 添加总卡路里变量
    在Fragment中声明用于存储总和的变量:
private var totalCalories = 0 // 存储选中项的卡路里总和
  1. 创建Adapter时传入回调逻辑
    修改getMyData方法中创建Adapter的代码,传入回调处理总和更新与界面展示:
override fun onResponse(
    call: Call<List<MyDataItem>?>,
    response: Response<List<MyDataItem>?>
) {
    val responseBody = response.body()!!
    adapterItem = AdapterItem(responseBody) { calories, isChecked ->
        // 更新总卡路里数值
        totalCalories += if (isChecked) calories else -calories
        // 将总和显示到界面的TextView中
        binding?.activitateTxt?.text = "总卡路里:$totalCalories"
    }
    recyclerview_lista.adapter = adapterItem
}
  1. 优化初始化时机
    原代码中getMyData在onCreateView中调用,可能导致RecyclerView未初始化完成,建议移到onViewCreated中:
override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    val fragmentBinding = FragmentInformationBinding.inflate(inflater, container, false)
    binding = fragmentBinding
    return fragmentBinding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    
    linearLayoutManager = LinearLayoutManager(this.context)
    recyclerview_lista.setHasFixedSize(true)
    recyclerview_lista.layoutManager = linearLayoutManager
    
    binding?.apply {
        viewModel = sharedViewModel
        informationFragment = this@InformationFragment
        lifecycleOwner = viewLifecycleOwner
    }
    
    getMyData() // 移到此处调用,确保RecyclerView已初始化
}

三、额外优化建议

  • 配置变化时保存状态:如果需要在屏幕旋转等配置变化时保留总卡路里数值,可通过onSaveInstanceState和onViewCreated实现:
override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    outState.putInt("TOTAL_CALORIES", totalCalories)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    // ... 原有代码 ...
    savedInstanceState?.let {
        totalCalories = it.getInt("TOTAL_CALORIES")
        binding?.activitateTxt?.text = "总卡路里:$totalCalories"
    }
    getMyData()
}
  • 用唯一标识替代position:如果MyDataItem有唯一ID,建议用ID代替position保存选中状态,避免数据更新时position错乱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 19:57:35