首页 > 解决方案 > 如何在 RecyclerView 中突出显示并自动单击最近添加的项目

问题描述

我有两个场景,所以第一个是我想突出显示并自动执行单击 RecyclerView 中最近添加的项目,第二个是如果用户选择或单击任何项​​目,该时间也应该突出显示和点击所以第二个场景我已经实现了,但我不知道如何突出显示并自动执行单击列表中最后添加的项目。

我的适配器类

class CarItemAdapter(
        private val activity: MainActivity,
        private val carList: ArrayList<MyEntity>,
        private val myViewModel: MyViewModel,
        private val settings: Settings
) :
        RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    var listener: OnItemsClickListener? = null
    var rowIndex = 0

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        return when (viewType) {
            VIEW_TYPE_ADDITEM -> ViewHolderAddCarItem(SettingsCarAddItemTileBinding.inflate(layoutInflater, parent, false))
            VIEW_TYPE_ITEM -> ViewHolderCarItem(SettingsCarItemTileBinding.inflate(layoutInflater, parent, false))
            else -> throw IllegalArgumentException("Invalid view type")
        }
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {

        when (holder) {
            is ViewHolderCarItem -> holder.bind(carList[position -1], position-1)
            is ViewHolderAddCarItem -> holder.bind()
        }
    }

    inner class ViewHolderAddCarItem internal constructor(private var binding: SettingsCarAddItemTileBinding) : RecyclerView.ViewHolder(binding.root) {
        fun bind() {
            binding.lifecycleOwner = activity
            binding.handler = EventHandler()
            binding.userSpecificCarSubtitle.setText(R.string.user_specific_car_subtitle)
        }

        inner class EventHandler {
            fun onItemClicked() {
                activity.showSubPage(AddVehiclePage(activity), true)
            }
        }
    }

    inner class ViewHolderCarItem internal constructor(private var binding: SettingsCarItemTileBinding) : RecyclerView.ViewHolder(binding.root) {
        fun bind(myEntity: MyEntity, position: Int) {

            binding.lifecycleOwner = activity
            val bmp = BitmapFactory.decodeByteArray(myEntity.image, 0, Objects.requireNonNull<ByteArray>(myEntity.image).size)
            binding.carImage.setImageBitmap(bmp)
            binding.carName.text = myEntity.label

            binding.layoutCar.setOnClickListener {
                listener?.onItemClick(myEntity)
                settings.carNumber = myEntity.carNumber
                settings.selectedCarType = activity.getString(R.string.settings_category_view_sub_title_for_user_specific_car)
                settings.isCarSelected = true
                rowIndex = position
                notifyDataSetChanged()
            }

            binding.deleteButton.setOnClickListener {
                GlobalScope.launch(Dispatchers.IO) { bbdCarViewModel.deleteByFinNumber(myEntity.carNumber) }
                settings.isBBDCarSelected = false
                carList.removeAt(position)
                notifyDataSetChanged()
            }

            if (rowIndex == position) {
                binding.layoutCar.setBackgroundColor(activity.getColor(R.color.petrol))
                binding.carName.setTextColor(activity.getColor(R.color.white))
            } else {
                binding.layoutCar.setBackgroundColor(activity.getColor(R.color.coolGray))
                binding.carName.setTextColor(activity.getColor(R.color.coolGray_80k))
            }
        }
    }

    override fun getItemViewType(position: Int): Int {
        return if (position == 0 && position <= carList.size) {
            VIEW_TYPE_ADDITEM
        } else VIEW_TYPE_ITEM
    }

    override fun getItemCount(): Int {
        return carList.size + 1
    }

    interface OnItemsClickListener {
        fun onItemClick(myEntity: MyEntity)
    }

    fun setWhenClickListener(listener: OnItemsClickListener) {
        this.listener = listener
    }

    companion object {
        const val VIEW_TYPE_ITEM = 0
        const val VIEW_TYPE_ADDITEM = 1
    }
}

请帮我

标签: androidkotlinarraylistandroid-recyclerviewadapter

解决方案


我们可以为适配器类添加占位符,并通过唯一的 id 在其中存储突出显示的项目。然后在绑定函数中,我们可以突出显示具有这些 id 的项目:

1.添加占位符

我们可以使用占位符来保存突出显示的项目来处理活动状态。

它可能是一个 HashSet , Long 的类型是用于项目 id 的,我们将在 init 块中将其设置为稳定。

class CarItemAdapter(...) : ... {
...
val activeHolder: HashSet<Long> = HashSet()
    
init {
    // Represents each item in the data set with a unique indentifier
    setHasStableIds(true)
 }
...


2.将最近添加的项目添加到placeHolder

现在我们为每个项目获得了一个唯一标识符,以及一个用于保存突出显示项目的活动状态的占位符。

我们希望最后添加的项目被突出显示,所以假设您在 EventHandler 的 onclick 方法中添加新项目,更新 mothed 如下:

inner class EventHandler {
            fun onItemClicked() {
                with(activeHolder){                  
                    val lastItemId = getItemId(carList.size - 1)
                    // Remove last item's id from our holder to prevent last two items being highlighted.
                    if (contains(lastItemId)) remove(lastItemId) 
                    // Suppose we add new item to carList here
                    carList.add(newItem)
                    // add last item id of new list to the holder   
                    add(getItemId(carList.size - 1))   
                }
                notifyDataSetChanged()
                
            }
        }

在上面的代码中,我们假设将新 Item 添加到 list 是 inside carList.add(newItem),如果不是这种情况,请将上面的 with(){} 代码块包裹在carList.add(newCar).


3.通过onClick动作添加和删除项目到占位符

这个很简单,只是一个单行:


binding.layoutCar.setOnClickListener {
    ...
    with(activeHolder) { if (contains(itemId)) remove(itemId) else add(itemId) }
    ...
notifyDataSetChanged()
}

4、压轴;执行突出显示


    inner class ViewHolderCarItem internal constructor(private var binding: SettingsCarItemTileBinding) : RecyclerView.ViewHolder(binding.root) {
        fun bind(myEntity: MyEntity, position: Int) {
            ...

            binding.layoutCar.setOnClickListener {
                ...
                with(activeHolder) { if (contains(itemId)) remove(itemId) else add(itemId) }
                ...
                notifyDataSetChanged()
            }

            binding.deleteButton.setOnClickListener {
                   ...
            }

            // Activates last item, or item's clicked
            itemView.isActivated = activeHolder.contains(itemId)

            if(itemView.isActivated) {
                // Do anything you want by highlighted items.
            }

        }
    }


我希望这个答案有所帮助。


更新

要执行单击最后一个突出显示的项目:

在活动的 onCreate() 方法中:

lifecycle.coroutineScope.launch {
            lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
                delay(300)
                recyclerView.findViewHolderForAdapterPosition(recyclerView.size-1)?.itemView?.performClick()
           }
}

注意:对于 repeatOnLifecycle() 方法,您需要androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha01依赖。


推荐阅读