如何实现RecyclerView选中项的卡路里数值求和功能?
实现RecyclerView项CheckBox勾选时累加卡路里总和的逻辑改造方案
一、改造AdapterItem类
需要在Adapter中处理CheckBox的选中状态,同时通过回调将选中事件传递给Fragment,具体修改如下:
- 添加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引用 }
- 维护选中状态集合与回调接口
在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的回调并更新总和,同时将结果显示到界面上:
- 添加总卡路里变量
在Fragment中声明用于存储总和的变量:
private var totalCalories = 0 // 存储选中项的卡路里总和
- 创建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 }
- 优化初始化时机
原代码中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
相关产品推荐
相关产品推荐

