RecyclerView 显示两个突出显示的项目

Posted

技术标签:

【中文标题】RecyclerView 显示两个突出显示的项目【英文标题】:RecyclerView showing two highlighted item 【发布时间】:2021-11-03 02:44:50 【问题描述】:

我有两种情况可以在 recyclerview 中突出显示该项目第一个是当用户单击任何项​​目以便突出显示单击的项目时,第二个情况是当最后一个或最近的项目添加到列表中时,最后添加的项目应该突出显示。

所以我的第一个场景(onClick)工作正常,但问题出在我的第二个场景中,所以每当我将项目添加到列表中时,两个项目都会突出显示。请建议我哪里错了。还有一件最近或最后一项也应该执行自动点击的事情。那么我该如何实现呢。

class CarItemAdapter(
        private val activity: MainActivity,
        private val carList: ArrayList<CarEntity>,
        private val carViewModel: CarViewModel,
        private val settings: Settings
) :
        RecyclerView.Adapter<RecyclerView.ViewHolder>() 
    var listener: OnItemsClickListener? = null
    var rowIndex = 100
    var listItemCount = 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(Car360AddVehiclePage(activity), true)
            
        
    

    inner class ViewHolderCarItem internal constructor(private var binding: SettingsCarItemTileBinding) : RecyclerView.ViewHolder(binding.root) 
        fun bind(carEntity: CarEntity, position: Int) 
            Timber.d("Data store position %s %s", position, carList.size)
            listItemCount = itemCount

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

            binding.layoutCar.setOnClickListener 
                listItemCount = 100
                listener?.onItemClick(carEntity)
                settings.finNumber = carEntity.finNumber
                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)  carViewModel.deleteByFinNumber(carEntity.finNumber) 
                carList.removeAt(position)
                notifyDataSetChanged()
            

            if(position == listItemCount-2)
                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))
            

            if (rowIndex == position) 
                binding.layoutCar.setBackgroundColor(activity.getColor(R.color.petrol))
                binding.carName.setTextColor(activity.getColor(R.color.white))
            
        
    

    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(carEntity: CarEntity)
    

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

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

MyFragmentSubPage :我将数据添加到列表中的位置

 if (isDialogVisible) 
            Dialog imageDownloadCheckDialog = Dialog.createProgressBarDialog(getContext(), R.string.image_progressbar_title);
            imageDownloadCheckDialog.setCancelable(false);
            imageDownloadCheckDialog.show();
            carViewModel.getGetDismissDialog().observe(getActivity(), isDismissDialog -> 
                if (isDismissDialog) 
                    imageDownloadCheckDialog.dismiss();
                    carViewModel.dismissDialog(false);
                    new Thread(() -> 
                        CarEntity carEntity = carViewModel.getImageFor340Degree(vinNumber, "340");
                        // Here I am adding data into the list
                        recyclerImageList.add(carEntity);
                    ).start();
                

            );
        
        
          RecyclerView recyclerView = binding.getRoot().findViewById(R.id.list);
        if (recyclerView != null) 
            layoutManager = new GridLayoutManager(getContext(), 2);
            recyclerView.setLayoutManager(layoutManager);
        

  carItemAdapter = new CarItemAdapter(getActivity(), recyclerImageList, eventHandler, carViewModel, settings);
            assert recyclerView != null;
            recyclerView.setAdapter(carItemAdapter);
            recyclerView.getRecycledViewPool().setMaxRecycledViews(carItemAdapter.VIEW_TYPE_ITEM, 50);

【问题讨论】:

【参考方案1】:

首先在您的适配器中创建一个CarEntity var,名为selectedCar

在适配器内部创建一个名为submitItem的函数

  fun submitItem(car: CarEntity) 
            selectedCar = car //set the selected car to the new car
            notifyItemChanged(rowIndex)//rebind old selected car
            carList.add(car) //add new car to list
            rowIndex = carList.size() - 1 //set current selected index
            notifyItemInserted(rowIndex)//notify the change at selected index
    

还有你的对话

                new Thread(() -> 
                    CarEntity carEntity = carViewModel.getImageFor340Degree(vinNumber, "340");
                    // Here I am adding data into the list
                    requireActivity().runOnUiThread
                          carItemAdapter.submitItem(carEntity);   
                    
                ).start();

还有你的按钮

binding.layoutCar.setOnClickListener 
                listItemCount = 100
                listener?.onItemClick(carEntity)
                settings.finNumber = carEntity.finNumber
                settings.selectedCarType = activity.getString(R.string.settings_category_view_sub_title_for_user_specific_car)
                

                selectedCar = carEntity //set the select car on click
                notifyItemChanged(rowIndex) //notify old row has changed
                notifyItemChanged(position) //notify new row has changed
                rowIndex = position // set current selected row
            

并在绑定时设置选定的视图内容

if(carEntity == selectedCar)
    //highlight row

【讨论】:

那么你是说如果你有5项目并选择项目1,那么现在添加一个项目项目56被选中或者是项目1和@987654333 @已选中。 我是说如果我在列表中有 5 项,那么我将在列表中添加第 6 项,因此第 5 和第 6 项会突出显示,而不是第 6 项。这里我不是点击或选择项目。 每当我将数据添加到列表中时,应该选择最近的项目,并且正如我已经提出问题的那样,我有 2 个场景,一个是 onClick 我必须突出显示选定的项目,第二个是如果数据将最近的项目应突出显示的时间添加到列表中 你能把你添加到列表中的那段代码贴出来并通知适配器更改吗? 在实现相同逻辑时遇到问题“android.view.ViewRootImpl$CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能接触其视图。”在这一行中 notifyItemChanged(rowIndex)//重新绑定老选中的车

以上是关于RecyclerView 显示两个突出显示的项目的主要内容,如果未能解决你的问题,请参考以下文章

如何正确突出显示 RecyclerView 上的选定项目?

为啥在recyclerview android中滚动后突出显示的项目丢失

如何突出显示 Recycler View 的选定项目?

RecyclerView 只显示一项

如何在 recyclerView 中的两个不同项目之间显示不同的项目?

使用 R 在美国地图中突出显示邮政编码