【问题标题】:How to highlight selected item in RecyclerView如何在 RecyclerView 中突出显示所选项目
【发布时间】:2022-02-23 19:14:36
【问题描述】:

我使用 RecyclerView 在我的图像编辑应用程序中显示缩略图。它的每个项目都包含一个 ImageView(thumbnail) 和一个 textView。在我的应用程序中,我想仅突出显示当前选定的缩略图已点击。浏览了 SO 上的所有相关帖子,但找不到更好的解决方案。

我的适配器类

    public class FiltersAdapter extends RecyclerView.Adapter<FiltersAdapter.ViewHolder> {

    private Context mContext;
    private List<Type> mDataSet;
    private Uri selectedPhoto;

    public enum Type {
        Original,
        Grayscale,
        Sepia,
        Contrast,
        Invert,
        Pixel,
        Sketch,
        Swirl,
        Brightness,
        Vignette
    }

    public FiltersAdapter(Context context, List<Type> dataSet, Uri selectedPhoto) {
        mContext = context;
        mDataSet = dataSet;
        this.selectedPhoto = selectedPhoto;
    }

    @Override
    public FiltersAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(mContext).inflate(R.layout.list_item_layout, parent, false);
        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(FiltersAdapter.ViewHolder holder, int position) {
        switch (mDataSet.get(position)) {
            case Original:
                holder.image.setImageResource(R.drawable.no_filter);
                break;
            case Grayscale:
                Picasso.with(mContext)
                        .load(R.drawable.no_filter)
                        .transform(new GrayscaleTransformation())
                        .into(holder.image);
                break;
            case Sepia:
                Picasso.with(mContext)
                        .load(R.drawable.no_filter)
                        .transform(new SepiaFilterTransformation(mContext))
                        .into(holder.image);
                break;
            case Contrast:
                Picasso.with(mContext)
                        .load(R.drawable.no_filter)
                        .transform(new ContrastFilterTransformation(mContext, 2.0f))
                        .into(holder.image);
                break;
            case Invert:
                Picasso.with(mContext)
                        .load(R.drawable.no_filter)
                        .transform(new InvertFilterTransformation(mContext))
                        .into(holder.image);
                break;
            case Pixel:
                Picasso.with(mContext)
                        .load(R.drawable.no_filter)
                        .transform(new PixelationFilterTransformation(mContext, 20))
                        .into(holder.image);
                break;
            case Sketch:
                Picasso.with(mContext)
                        .load(R.drawable.no_filter)
                        .transform(new SketchFilterTransformation(mContext))
                        .into(holder.image);
                break;
            case Swirl:
                Picasso.with(mContext)
                        .load(R.drawable.no_filter)
                        .transform(new SwirlFilterTransformation(mContext, 0.5f, 1.0f, new PointF(0.5f, 0.5f)))
                        .into(holder.image);
                break;
            case Brightness:
                Picasso.with(mContext)
                        .load(R.drawable.no_filter)
                        .transform(new BrightnessFilterTransformation(mContext, 0.5f))
                        .into(holder.image);
                break;
            case Vignette:
                Picasso.with(mContext)
                        .load(R.drawable.no_filter)
                        .transform(new VignetteFilterTransformation(mContext, new PointF(0.5f, 0.5f),
                                new float[]{0.0f, 0.0f, 0.0f}, 0f, 0.75f))
                        .into(holder.image);
                break;
            default:
                holder.image.setImageResource(R.drawable.no_filter);
                break;

        }
        holder.title.setText(mDataSet.get(position).name());
    }

    @Override
    public void onViewAttachedToWindow(ViewHolder holder) {
        super.onViewAttachedToWindow(holder);

    }

    @Override
    public int getItemCount() {
        return mDataSet.size();
    }

    @Override
    public int getItemViewType(int position) {
        return position;
    }

    static class ViewHolder extends RecyclerView.ViewHolder {

        public ImageView image;
        public TextView title;

        ViewHolder(View itemView) {
            super(itemView);
            image = (ImageView) itemView.findViewById(R.id.thumbnailImage);
            title = (TextView) itemView.findViewById(R.id.title);
        }


    }
}

片段代码

horizontalFilters = (RecyclerView) mView.findViewById(R.id.rvHorizontal);
    LinearLayoutManager horizontalLayoutManagaer
            = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false);
    horizontalFilters.setLayoutManager(horizontalLayoutManagaer);

    List<Type> dataSet = new ArrayList<>();
    dataSet.add(Type.Original);
    dataSet.add(Type.Grayscale);
    dataSet.add(Type.Sepia);
    dataSet.add(Type.Contrast);
    dataSet.add(Type.Invert);
    dataSet.add(Type.Pixel);
    dataSet.add(Type.Sketch);
    dataSet.add(Type.Swirl);
    dataSet.add(Type.Brightness);
    dataSet.add(Type.Vignette);

    horizontalFilters.setAdapter(new FiltersAdapter(act, dataSet, selectedPhotoUri));

    horizontalFilters.addOnItemTouchListener(new RecyclerClick(act, horizontalFilters, new RecyclerClickListener() {
        @Override
        public void onClick(View view, int position) {
            switch (position){
                case 0:
                    photo.setImageDrawable(drawable);
                    break;
                case 1:
                    Picasso.with(act)
                            .load(selectedPhotoUri)
                            .transform(new GrayscaleTransformation())
                            .into(photo);
                    break;
                case 2:
                    Picasso.with(act)
                            .load(selectedPhotoUri)
                            .transform(new SepiaFilterTransformation(act))
                            .into(photo);
                    break;
                case 3:
                    Picasso.with(act)
                            .load(selectedPhotoUri)
                            .transform(new ContrastFilterTransformation(act, 2.0f))
                            .into(photo);
                    break;
                case 4:
                    Picasso.with(act)
                            .load(selectedPhotoUri)
                            .transform(new InvertFilterTransformation(act))
                            .into(photo);
                    break;
                case 5:
                    Picasso.with(act)
                            .load(selectedPhotoUri)
                            .transform(new PixelationFilterTransformation(act, 20))
                            .into(photo);
                    break;
                case 6:
                    Picasso.with(act)
                            .load(selectedPhotoUri)
                            .transform(new SketchFilterTransformation(act))
                            .into(photo);
                    break;
                case 7:
                    Picasso.with(act)
                            .load(selectedPhotoUri)
                            .transform(new SwirlFilterTransformation(act, 0.5f, 1.0f, new PointF(0.5f, 0.5f)))
                            .into(photo);
                    break;
                case 8:
                    Picasso.with(act)
                            .load(selectedPhotoUri)
                            .transform(new BrightnessFilterTransformation(act, 0.5f))
                            .into(photo);
                    break;
                case 9:
                    Picasso.with(act)
                            .load(selectedPhotoUri)
                            .transform(new VignetteFilterTransformation(act, new PointF(0.5f, 0.5f),
                                    new float[]{0.0f, 0.0f, 0.0f}, 0f, 0.75f))
                            .into(photo);
                    break;
                default:
                    photo.setImageDrawable(drawable);
                    break;
            }
        }

        @Override
        public void onLongClick(View view, int position) {

        }
    }));
}

【问题讨论】:

  • 您是否有任何 clickListener 或其他东西,以便您知道您选择/点击了某些东西?
  • 是的,我使用了自定义的监听器...你要我添加那个代码吗?
  • 是否可以将'public enum Type'作为模型更改为'public class Type'??

标签: android android-recyclerview


【解决方案1】:

只需在 bindView 中添加以下行

holder.itemView.setBackgroundColor(Color.parseColor("#000000"));

会为你工作。

如果您想突出显示选定的项目,只需执行以下操作

全局设置

int selectedPosition=-1;

onBindViewHolder 内部-

public void onBindViewHolder(FiltersAdapter.ViewHolder holder, int position) {
if(selectedPosition==position)
  holder.itemView.setBackgroundColor(Color.parseColor("#000000"));
else
  holder.itemView.setBackgroundColor(Color.parseColor("#ffffff"));

holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                selectedPosition=position;
                notifyDataSetChanged();

            }
        });
}

================================================ =============

上面的代码按照老派的方法可以正常工作,但这里是可能对您有所帮助的更新版本:

Kotlin-

如果您想突出显示选定的项目,请遵循:

var selectedPosition = -1; //make it global

onBindViewHolder 内部-

override fun onBindViewHolder(holder: FiltersAdapter.ViewHolder, position: Int) {
            if (selectedPosition == position)
                holder.itemView.setBackgroundColor(Color.parseColor("#000000"))
            else
                holder.itemView.setBackgroundColor(Color.parseColor("#ffffff"))
        }

并创建实现View.OnClickListener 的内部类ViewHolder 并覆盖onClick 函数。

override fun onClick(v: View) {
      when (v.id) {
           R.id.parent-> {
               selectedPosition = adapterPosition;
                        notifyDataSetChanged();
               }
           }
       }

干杯。

【讨论】:

  • 努力工作......它为整个回收站视图添加了背景
  • 它只会为你 recycleView 的项目而不是 recycleView 添加背景。而且您的项目不包含边距,因此它会填充您的整个回收视图,为您的项目布局添加边距。
  • 但我也想取消选择之前选择的项目并仅突出显示并发项目...您的答案没有这样做...它仅将背景设置为项目
  • 也 - 不能在回调中使用位置,因为它没有用 final 声明
  • 使用 notifyItemChanged(selectedPosition) 代替 notifyDataSetChanged();
【解决方案2】:

使用背景选择器并在布局 xml 的 android:background 属性中为 recyclerview 项设置它

background_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="false" android:state_selected="true">
        <shape>
            <solid android:color="@color/lightPrimaryColor" />
        </shape>
    </item>

    <item android:state_selected="false">
        <shape>
            <solid android:color="@android:color/transparent" />
        </shape>
    </item>
</selector>

recyclerview_item.xml(background_selector 在 android:background 属性中设置)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/background_selector"
    android:orientation="vertical"
    android:paddingBottom="8dp"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:paddingTop="8dp">

然后在你获得点击事件的地方,你可以使用 View 函数将其设置为选中

view.setSelected(true)

您必须通过存储所选项目的位置来实现何时取消选择/选择项目的逻辑

【讨论】:

  • 需要在全局变量中取之前选中的视图,并且需要使选中为false
【解决方案3】:

可能只是使用:

android:background="?attr/selectableItemBackground"

对于项目 xml 的根元素?

【讨论】:

  • 应该是android:background="?android:attr/selectableItemBackground"
【解决方案4】:

创建模型日历模型名称

class CalenderModel {
var date: String
var isselected: Boolean
constructor(date: String, isselected: Boolean) {
    this.date = date
    this.isselected = isselected
}
 }

创建适配器 CalenderAdapter 名称

class CalenderAdapter(
internal var activity: Activity,
internal var calenderModelList: ArrayList<CalenderModel>
) : RecyclerView.Adapter<CalenderAdapter.MyViewHolder>() {
var selected_defoult = 0
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
    val itemView: View
    itemView =
        LayoutInflater.from(parent.context).inflate(R.layout.item_calenderdate, 
parent, false)
    return MyViewHolder(itemView)
}

override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
    val list = calenderModelList.get(position)
    holder.date_tv.text = Common.formateDate_calender_date(list.date)
    holder.day_tv.text = Common.formateDate_calender_day(list.date)
    if (position <= 3) {
        if (list.isselected) {
            holder.mLinearLayout.setBackgroundDrawable(
                ContextCompat.getDrawable(
                    activity,
                    R.drawable.selected_calender_background_green
                )
            )
        } else {
            holder.mLinearLayout.setBackgroundDrawable(
                ContextCompat.getDrawable(
                    activity,
                    R.drawable.selected_calender_background_gray
                )
            )
        }
    } else {
        holder.mLinearLayout.setBackgroundDrawable(
            ContextCompat.getDrawable(
                activity,
                R.drawable.selected_calender_background_gray_light
            )
        )
    }

    holder.itemView.setOnClickListener {
        if (position <= 3) {
            calenderModelList.get(selected_defoult).isselected = false
            calenderModelList.get(position).isselected = true
            selected_defoult = position
            notifyDataSetChanged()
        }
    }

   }

 override fun getItemCount(): Int {
    return calenderModelList.size
 }

override fun getItemId(position: Int): Long {
    return position.toLong()
}

override fun getItemViewType(position: Int): Int {
    return position
}


inner class MyViewHolder
internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {

    val day_tv: TextView
    val date_tv: TextView
    val mLinearLayout: LinearLayout

    init {
        mLinearLayout = itemView.findViewById(R.id.mLinearLayout)
        day_tv = itemView.findViewById(R.id.day_tv)
        date_tv = itemView.findViewById(R.id.date_tv)

    }
 }


 }

【讨论】:

    【解决方案5】:

    所以我们在回收站视图中有一个类 ViewHolder 和一个方法 OnBindViewHolder() 好吗? 现在,当您单击回收器视图中的项目时,将从视图持有者类中为该视图调用 OnClickMethod。现在创建一个整数变量int previousClickedItemPosition = -1 ;

    现在在 viewHolderClass 的 onClickListener 方法中放入这一行, previousClickedItemPosition = getAdapterPosition(); 从这里我们可以得到我们最近点击的项目的位置。

    现在在 OnBindViewHolder() 中将项目背景的颜色设置为蓝色,

    holder.fileNameTextView.setTextColor(Color.BLUE)

    现在在 OnclickListener 中放入这些行

    holder.fileNameTextView.setTextColor(Color.YELLOW);
    
    if(previousClickedItemPosition != getAdapterPosition()) {
    notifyDataSetchanged(previousClickedItemPosition );
    }
    

    提示是,当我们调用 notifyDataSetchanged 时,就会调用 onBindViewHolder。

    所以当您启动回收站视图时,所有颜色都将变为蓝色。 当您单击一个项目颜色将是黄色的。 当您单击下一个项目时,上一个项目的颜色将为蓝色,对于当前项目,颜色将为黄色。

    【讨论】:

      【解决方案6】:

      将您的枚举更新为首先作为标志的类

      public class Type {
          public int type; // 0-Original,1-Grayscale,2-Sepia.... same as enum
          public int selected;
      }
      

      现在在适配器中

      @Override
      public void onBindViewHolder(FiltersAdapter.ViewHolder holder, int position) {
          int typeOfItem = mDataSet.get(position).type
          switch (mDataSet.get(position)) {
              case 0:
                  holder.image.setImageResource(R.drawable.no_filter);
                  break;
              case 1:
                  Picasso.with(mContext)
                          .load(R.drawable.no_filter)
                          .transform(new GrayscaleTransformation())
                          .into(holder.image);
                  break;
              case 2:
                  Picasso.with(mContext)
                          .load(R.drawable.no_filter)
                          .transform(new SepiaFilterTransformation(mContext))
                          .into(holder.image);
                  break;
              case 3:
                  Picasso.with(mContext)
                          .load(R.drawable.no_filter)
                          .transform(new ContrastFilterTransformation(mContext, 2.0f))
                          .into(holder.image);
                  break;
              case 4:
                  Picasso.with(mContext)
                          .load(R.drawable.no_filter)
                          .transform(new InvertFilterTransformation(mContext))
                          .into(holder.image);
                  break;
              case 5:
                  Picasso.with(mContext)
                          .load(R.drawable.no_filter)
                          .transform(new PixelationFilterTransformation(mContext, 20))
                          .into(holder.image);
                  break;
              case 6:
                  Picasso.with(mContext)
                          .load(R.drawable.no_filter)
                          .transform(new SketchFilterTransformation(mContext))
                          .into(holder.image);
                  break;
              case 7:
                  Picasso.with(mContext)
                          .load(R.drawable.no_filter)
                          .transform(new SwirlFilterTransformation(mContext, 0.5f, 1.0f, new PointF(0.5f, 0.5f)))
                          .into(holder.image);
                  break;
              case 8:
                  Picasso.with(mContext)
                          .load(R.drawable.no_filter)
                          .transform(new BrightnessFilterTransformation(mContext, 0.5f))
                          .into(holder.image);
                  break;
              case 9:
                  Picasso.with(mContext)
                          .load(R.drawable.no_filter)
                          .transform(new VignetteFilterTransformation(mContext, new PointF(0.5f, 0.5f),
                                  new float[]{0.0f, 0.0f, 0.0f}, 0f, 0.75f))
                          .into(holder.image);
                  break;
              default:
                  holder.image.setImageResource(R.drawable.no_filter);
                  break;
          }
          holder.title.setText(mDataSet.get(position).name());
          if(mDataSet.get(position).selected == 0){
              holder.title.setTypeface(null, Typeface.BOLD);
          } else {
              holder.title.setTypeface(null,Typeface.NORMAL);
          }
      }
      

      不是每次点击或选择更新您的列表,然后调用适配器的 notifydatasetChanged()

      【讨论】:

        【解决方案7】:

        在 Kotlin 中,您可以简单地执行一些人已经提到的 Java。你把这段代码放在你的适配器类中。

        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            if (position < numItems) {
                // Bind your view here
                holder.itemView.setOnClickListener {
                    it.setBackgroundResource(R.color.lightBlue)
                }
            }
        }
        

        【讨论】:

          【解决方案8】:
          android:background="?attr/selectableItemBackground"
          android:clickable="true"
          android:focusableInTouchMode="true"
          

          【讨论】:

            【解决方案9】:

            如果您想使用 notifyDataSetChanged
            由 kotlin 实现

             override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
                adapterOrders = OrdersSendAdapter(this, listOrders)
                recyclerOrders = view.findViewById<RecyclerView>(R.id.recycler_orders)
                recyclerOrders.layoutManager = LinearLayoutManager(activity)
                recyclerOrders.setHasFixedSize(true)
                recyclerOrders.addItemDecoration(DividerItemDecoration(activity, DividerItemDecoration.VERTICAL))
                recyclerOrders.adapter = adapterOrders
              }
            
            /* This method will be call when item of adapter has an event */
            fun getListDetail(position: Int, idOrders: String) {
                for (index in 0 until recyclerOrders.childCount) {
                     recyclerOrders[index].setBackgroundColor(Color.parseColor("#ffffff"))
                }
                recyclerOrders[position].setBackgroundColor(ContextCompat.getColor(context!!, R.color.color_select))
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-08-22
              • 1970-01-01
              • 2014-12-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-08-31
              相关资源
              最近更新 更多