Hola, estoy trabajando en Android Kotlin. Estoy trabajando en reyclerview. Quiero hacer una selección única en mis artículos. Probé un código que funciona bien.
OpcionesViewAdapter.kt
class OptionsViewAdapter : ListAdapter<ProductVariant, OptionsViewHolder>(PRODUCT_COMPARATOR) { private var selectedItemPosition: Int = 0 companion object { private val PRODUCT_COMPARATOR = object : DiffUtil.ItemCallback<ProductVariant>() { override fun areItemsTheSame( oldItem: ProductVariant, newItem: ProductVariant ): Boolean { return oldItem == newItem } override fun areContentsTheSame( oldItem: ProductVariant, newItem: ProductVariant ): Boolean { return oldItem == newItem } } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OptionsViewHolder { return OptionsViewHolder.bindView(parent) } override fun onBindViewHolder(holder: OptionsViewHolder, position: Int) { holder.binding.root.setOnClickListener { selectedItemPosition = holder.bindingAdapterPosition notifyAdapter() } val drawableColor = if (selectedItemPosition == position) R.drawable.options_item_selected_background else R.drawable.options_item_default_background holder.binding.root.background = ContextCompat.getDrawable(holder.binding.root.context, drawableColor) holder.bindItem(getItem(position), position) } fun notifyAdapter() { notifyDataSetChanged() } }OpcionesViewHolder.kt
class OptionsViewHolder( val binding: OptionsItemLayoutBinding, ) : RecyclerView.ViewHolder(binding.root) { companion object { fun bindView(parent: ViewGroup): OptionsViewHolder { return OptionsViewHolder( OptionsItemLayoutBinding.inflate( LayoutInflater.from(parent.context), parent, false ) ) } } fun bindItem(item: ProductVariant?, position: Int) { } }El video para un solo clic funciona bien.
Cuando muevo el código onBindViewHolder dentro bindItem , no funciona. Alguien me puede orientar por qué sucede esto.
contra
OpcionesViewAdapter.kt
class OptionsViewAdapter : ListAdapter<ProductVariant, OptionsViewHolder>(PRODUCT_COMPARATOR) { companion object { private val PRODUCT_COMPARATOR = object : DiffUtil.ItemCallback<ProductVariant>() { override fun areItemsTheSame( oldItem: ProductVariant, newItem: ProductVariant ): Boolean { return oldItem == newItem } override fun areContentsTheSame( oldItem: ProductVariant, newItem: ProductVariant ): Boolean { return oldItem == newItem } } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OptionsViewHolder { return OptionsViewHolder.bindView(parent) } override fun onBindViewHolder(holder: OptionsViewHolder, position: Int) { holder.bindItem(getItem(position), position ,::notifyAdapter) } fun notifyAdapter() { notifyDataSetChanged() } }OpcionesViewHolder.kt
class OptionsViewHolder( val binding: OptionsItemLayoutBinding, ) : RecyclerView.ViewHolder(binding.root) { private var selectedItemPosition: Int = 0 companion object { fun bindView(parent: ViewGroup): OptionsViewHolder { return OptionsViewHolder( OptionsItemLayoutBinding.inflate( LayoutInflater.from(parent.context), parent, false ) ) } } fun bindItem( item: ProductVariant?, position: Int, onAdapterChange: () -> Unit ) { binding.root.setOnClickListener { selectedItemPosition = position onAdapterChange() } val drawableColor = if (selectedItemPosition == position) R.drawable.options_item_selected_background else R.drawable.options_item_default_background binding.root.background = ContextCompat.getDrawable(binding.root.context, drawableColor) } }El video para un solo clic no funciona.
A pesar de que está pasando la referencia del método notifyAdapter() al Adaptador () en la función bindItem() , no lo está llamando en OnClickListener , por eso no funciona.
Movió la posición del elemento selectedItemPosition a la clase ViewHolder, por lo que tiene una copia separada de esta propiedad para cada instancia de la clase ViewHolder, por lo que ya no afecta a otros elementos de la lista cuando se hace clic en cualquier elemento de la lista.
Esto sería mucho más fácil de implementar haciendo que la clase del titular de la vista sea una clase inner class del adaptador para que pueda modificar directamente la propiedad selectedItemPosition del adaptador. Y le daría a la propiedad un setter personalizado para que pueda notificar automáticamente el cambio al adaptador en lugar de tener que trabajar con una llamada de función separada. También puede hacer que notifique al adaptador específicamente qué dos elementos de fila cambiaron en lugar de todo el conjunto de datos (más eficiente y al hacerlo en el configurador de propiedades, tiene acceso fácilmente a las posiciones de fila nuevas y antiguas en un solo lugar: field y value ).
private var selectedItemPosition: Int = 0 set(value) { val oldPos = field field = value notifyItemChanged(oldPos) notifyItemChanged(value) }