Android Studio(Kotlin&XML):RecyclerView卡片集成Switch及选中项同步至汇总页
医疗提醒App核心功能实现指导(选中治疗项同步至汇总页+提醒频率设置)
需求概述
我正在开发一款医疗提醒App,核心流程与待实现功能如下:
- 首页支持选择治疗类别
- 进入对应类别页后,通过RecyclerView卡片内的Switch选择具体治疗项
- 选中治疗项后,点击「医疗包」图标进入汇总页,需实现:
- 开启Switch时,汇总页自动生成带对应治疗名称和颜色的卡片
- 汇总页支持为每个治疗项设置提醒频率
项目资源
- 项目仓库:medminder-android
- 页面截图:
- 首页:

- 治疗页:

- 汇总页:

- 首页:
分步实现方案
1. 定义数据模型与状态管理
首先统一治疗项的数据结构,确保跨页面数据一致性:
// 治疗项数据类,包含核心属性 data class TreatmentItem( val id: String, val name: String, val colorHex: String, var isSelected: Boolean = false, var reminderFrequency: Int = 0 // 可定义为小时/天单位,根据需求调整 )
使用全局ViewModel维护选中状态,实现跨页面实时同步:
class TreatmentViewModel : ViewModel() { private val _selectedTreatments = MutableLiveData<MutableList<TreatmentItem>>() val selectedTreatments: LiveData<MutableList<TreatmentItem>> = _selectedTreatments init { // 初始化时可加载本地存储数据(见下文持久化部分) _selectedTreatments.value = mutableListOf() } // 更新治疗项选中状态 fun updateTreatmentSelection(item: TreatmentItem) { val currentList = _selectedTreatments.value ?: mutableListOf() if (item.isSelected) { currentList.add(item) } else { currentList.removeIf { it.id == item.id } } _selectedTreatments.postValue(currentList) // 同步保存到本地(见下文持久化部分) saveSelectedTreatments(currentList) } }
2. 治疗页Switch状态绑定与监听
在治疗页的RecyclerView Adapter中,绑定Switch状态并同步到ViewModel:
class TreatmentAdapter( private val treatmentList: List<TreatmentItem>, private val viewModel: TreatmentViewModel ) : RecyclerView.Adapter<TreatmentAdapter.ViewHolder>() { inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val card: CardView = itemView.findViewById(R.id.treatment_card) val nameTv: TextView = itemView.findViewById(R.id.treatment_name) val selectSwitch: Switch = itemView.findViewById(R.id.select_switch) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_treatment_card, parent, false) return ViewHolder(view) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val item = treatmentList[position] // 绑定UI属性 holder.card.setCardBackgroundColor(Color.parseColor(item.colorHex)) holder.nameTv.text = item.name holder.selectSwitch.isChecked = item.isSelected // 监听Switch状态变化 holder.selectSwitch.setOnCheckedChangeListener { _, isChecked -> item.isSelected = isChecked viewModel.updateTreatmentSelection(item) } } override fun getItemCount() = treatmentList.size }
3. 汇总页实时展示与频率设置
在汇总页监听ViewModel的LiveData,实时更新RecyclerView:
class SummaryActivity : AppCompatActivity() { private lateinit var viewModel: TreatmentViewModel private lateinit var adapter: SummaryAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_summary) viewModel = ViewModelProvider(this)[TreatmentViewModel::class.java] initRecyclerView() observeSelectedTreatments() } private fun observeSelectedTreatments() { viewModel.selectedTreatments.observe(this) { items -> adapter.updateItems(items) } } private fun initRecyclerView() { adapter = SummaryAdapter(mutableListOf()) { item, newFrequency -> // 更新治疗项的提醒频率 item.reminderFrequency = newFrequency viewModel.updateTreatmentSelection(item) } findViewById<RecyclerView>(R.id.summary_recycler).apply { adapter = this@SummaryActivity.adapter layoutManager = LinearLayoutManager(this@SummaryActivity) } } }
汇总页Adapter实现频率设置功能:
class SummaryAdapter( private var items: MutableList<TreatmentItem>, private val onFrequencyChanged: (TreatmentItem, Int) -> Unit ) : RecyclerView.Adapter<SummaryAdapter.ViewHolder>() { fun updateItems(newItems: MutableList<TreatmentItem>) { items = newItems notifyDataSetChanged() } inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val card: CardView = itemView.findViewById(R.id.summary_card) val nameTv: TextView = itemView.findViewById(R.id.treatment_name) val frequencySpinner: Spinner = itemView.findViewById(R.id.frequency_spinner) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_summary_card, parent, false) return ViewHolder(view) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val item = items[position] holder.card.setCardBackgroundColor(Color.parseColor(item.colorHex)) holder.nameTv.text = item.name // 绑定频率选择器 holder.frequencySpinner.setSelection(item.reminderFrequency) holder.frequencySpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { onFrequencyChanged(item, position) } override fun onNothingSelected(parent: AdapterView<*>?) {} } } override fun getItemCount() = items.size }
4. 持久化存储(可选但推荐)
避免App重启后数据丢失,将选中项序列化存储到SharedPreferences:
// 保存选中项到本地 fun saveSelectedTreatments(items: List<TreatmentItem>) { val gson = Gson() val json = gson.toJson(items) getSharedPreferences("MedMinderPrefs", Context.MODE_PRIVATE) .edit() .putString("selected_treatments", json) .apply() } // 从本地加载选中项 fun loadSelectedTreatments(context: Context): List<TreatmentItem> { val json = context.getSharedPreferences("MedMinderPrefs", Context.MODE_PRIVATE) .getString("selected_treatments", "") return if (json.isNullOrEmpty()) { emptyList() } else { Gson().fromJson(json, object : TypeToken<List<TreatmentItem>>() {}.type) } }
在ViewModel初始化时加载本地数据:
init { val savedItems = loadSelectedTreatments(context).toMutableList() _selectedTreatments.value = savedItems }
内容的提问来源于stack exchange,提问作者MobileMilin
相关产品推荐
相关产品推荐

