在我的应用程序中,我有
RecyclerView
并使用 DiffUtils 作为 recyclerview
的 Adapter。
更改背景颜色项目的
recyclerview
。 class HeartRateAdapter @Inject constructor() : RecyclerView.Adapter<HeartRateAdapter.ViewHolder>() {
private lateinit var binding: ItemSelectDialogBinding
private lateinit var context: Context
private var moviesList = emptyList<Data>()
private var selectedItem = -1
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
binding = ItemSelectDialogBinding.inflate(LayoutInflater.from(parent.context), parent, false)
context = parent.context
return ViewHolder()
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
//getItem from PagingDataAdapter
holder.bind(moviesList[position])
//Not duplicate items
holder.setIsRecyclable(false)
}
override fun getItemCount() = moviesList.size
inner class ViewHolder : RecyclerView.ViewHolder(binding.root) {
@SuppressLint("SetTextI18n")
fun bind(item: Data) {
binding.apply {
selectedTxt.text = item.description
//Click
binding.root.setOnClickListener {
selectedItem = adapterPosition
notifyDataSetChanged()
onItemClickListener?.let {
it(item)
}
}
//Change color
if (selectedItem == adapterPosition) {
binding.selectedImg.setImageResource(R.drawable.bg_circle_selected)
} else {
binding.selectedImg.setImageResource(R.drawable.bg_circle_un_selected)
}
}
}
}
private var onItemClickListener: ((Data) -> Unit)? = null
fun setOnItemClickListener(listener: (Data) -> Unit) {
onItemClickListener = listener
}
fun setData(data: List<Data>) {
val moviesDiffUtil = NotesDiffUtils(moviesList, data)
val diffUtils = DiffUtil.calculateDiff(moviesDiffUtil)
moviesList = data
diffUtils.dispatchUpdatesTo(this)
}
class NotesDiffUtils(private val oldItem: List<Data>, private val newItem: List<Data>) : DiffUtil.Callback() {
override fun getOldListSize(): Int {
return oldItem.size
}
override fun getNewListSize(): Int {
return newItem.size
}
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldItem[oldItemPosition] === newItem[newItemPosition]
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldItem[oldItemPosition] === newItem[newItemPosition]
}
}
}
要在单击 RecyclerView 中的项目时更改其背景颜色,您可以按照使用 Kotlin 的 Android 开发中的这些常规步骤进行操作。请记住,此示例假设您对设置 RecyclerView 及其适配器有基本的了解。
我更愿意将选定的状态保存在数据模型中。假设您有一个像这样的数据模型来显示名称列表:
data class Data(
val name: String,
val isSelected: Boolean
)
这就是 ViewModel 中 UI 状态的内容。
class SampleViewModel: ViewModel {
private val _uiState: MutableStateFlow<List<Data>>
val uiState: StateFlow<List<Data> = _uiState.asStateFlow()
// A function to change the state of a view when the user clicks on it
fun onItemClicked(position: Int) {
_uiState.update { items ->
items.mapIndexed { index, item ->
item.copy(isSelected = index == position)
}
}
}
}
然后你需要在你的Fragment/Activity中收集这个状态,但在此之前,最好为我们的recyclerview适配器创建另一个数据模型。这样您就可以区分 UI 逻辑和业务逻辑。
data class NameItem(
val name: String,
val backgroundColor: Int
)
然后你的片段会是这样的:
class MyFragment : Fragment() {
private val viewModel: SampleViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val binding = FragmentMyBinding.inflate(inflater, container, false)
val adapter = MyAdapter { position ->
viewModel.onItemClicked(position)
}
binding.recyclerView.layoutManager = LinearLayoutManager(requireContext())
binding.recyclerView.adapter = adapter
// Observe the ViewModel's UI state
lifecycleScope.launchWhenStarted {
viewModel.uiState.collect { newData ->
// Map Data to NameItem and update the adapter
val mappedData = newData.map { mapToNameItem(it) }
adapter.submitList(mappedData)
}
}
return binding.root
}
private fun mapToNameItem(data: Data): NameItem {
return NameItem(data.name, if (data.isSelected) Color.BLUE else Color.WHITE)
}
}
适配器会是这样的。它只设置背景颜色,没有任何逻辑。
// RecyclerView Adapter
class MyAdapter(private val onItemClick: (position: Int) -> Unit) :
RecyclerView.Adapter<MyAdapter.ViewHolder>() {
private var data: List<Data> = emptyList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemLayoutBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
return ViewHolder(binding)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = data[position]
holder.bind(item)
holder.itemView.setOnClickListener { onItemClick(position) }
}
override fun getItemCount(): Int = data.size
fun setData(newData: List<Data>) {
data = newData
notifyDataSetChanged()
}
class ViewHolder(private val binding: ItemLayoutBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(item: Data) {
binding.nameTextView.text = item.name
binding.root.setBackgroundColor(item.backgroundColor)
}
}
}
希望您觉得它有帮助。