在recyclerview中更改所选项目的背景颜色

问题描述 投票:39回答:12

如何在循环视图示例中仅更改所选视图的背景颜色?只需更改单击项目视图的背景颜色。一次只能显示一个选定项目,背景颜色会发生变化,其余项目必须与选择前一样。这是我的代码:

主要信息

public class MainActivity extends AppCompatActivity {
RecyclerView rv1;
    private  final String android_versions[]={
                "Donut",
                "Eclair",
                "Froyo",
                "Gingerbread",
                "Honeycomb",
                "Ice Cream Sandwich",
                "Jelly Bean",
                "KitKat",
                "Lollipop",
                "Marshmallow"
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();
    }

    private  void initViews(){
        rv1=(RecyclerView)findViewById(R.id.recyclerView1);
        rv1.setHasFixedSize(true);
        RecyclerView.LayoutManager layoutManager=new LinearLayoutManager(getApplicationContext());
        rv1.setLayoutManager(layoutManager);

        RecyclerDataAdapter rda=new RecyclerDataAdapter(rv1,getApplicationContext(),android_versions);
        rv1.setAdapter(rda);
    }
}

RecyclerDataadapter

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

private String android_versionnames[];
    private Context context1;

    private RecyclerView mRecyclerView;


    public RecyclerDataAdapter(RecyclerView recylcerView,Context context,String android_versionnames[]){
        this.android_versionnames=android_versionnames;
        this.context1=context;
mRecyclerView=recylcerView;
        setHasStableIds(true);
        System.out.println("Inside dataadapter,Android names : \n ");
        for(int i=0;i<android_versionnames.length;i++){
            System.out.println("\n"+android_versionnames[i]);
        }
    }


    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.row_layout,parent,false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        holder.tv1.setText(android_versionnames[position]);
    }


    @Override
    public int getItemCount() {
        return android_versionnames.length;
    }


    public class ViewHolder extends RecyclerView.ViewHolder {
        private TextView tv1;
        LinearLayout row_linearlayout;
        RecyclerView rv2;

        public ViewHolder(final View itemView) {
            super(itemView);
            tv1=(TextView)itemView.findViewById(R.id.txtView1);
            row_linearlayout=(LinearLayout)itemView.findViewById(R.id.row_linrLayout);
            rv2=(RecyclerView)itemView.findViewById(R.id.recyclerView1);
            /*itemView.setBackgroundColor(0x00000000);//to transparent*/

        }
    }
}
android background android-recyclerview
12个回答
84
投票

最后,我得到了答案。

public void onBindViewHolder(final ViewHolder holder, final int position) {
        holder.tv1.setText(android_versionnames[position]);

        holder.row_linearlayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                row_index=position;
                notifyDataSetChanged();
            }
        });
        if(row_index==position){
            holder.row_linearlayout.setBackgroundColor(Color.parseColor("#567845"));
            holder.tv1.setTextColor(Color.parseColor("#ffffff"));
        }
        else
        {
            holder.row_linearlayout.setBackgroundColor(Color.parseColor("#ffffff"));
            holder.tv1.setTextColor(Color.parseColor("#000000"));
        }

    }

这里'row_index'最初设置为'-1'

public class ViewHolder extends RecyclerView.ViewHolder {
        private TextView tv1;
        LinearLayout row_linearlayout;
        RecyclerView rv2;

        public ViewHolder(final View itemView) {
            super(itemView);
            tv1=(TextView)itemView.findViewById(R.id.txtView1);
            row_linearlayout=(LinearLayout)itemView.findViewById(R.id.row_linrLayout);
            rv2=(RecyclerView)itemView.findViewById(R.id.recyclerView1);
        }
    }

0
投票

我设法从我的Activity中执行此操作,其中我设置了Rv而不是来自适配器

如果有人需要做类似的事情,这里是代码

在这种情况下,logClick上的颜色会发生变化

           @Override
        public void onLongClick(View view, int position) {
            Toast.makeText(UltimasConsultasActivity.this, "Item agregado a la lista de mails",
                    Toast.LENGTH_SHORT).show();

            sendMultipleMails.setVisibility(View.VISIBLE);
            valueEmail.setVisibility(View.VISIBLE);
            itemsSeleccionados.setVisibility(View.VISIBLE);

            listaEmails.add(superListItems.get(position));
            listaItems ="";
            NameOfyourRecyclerInActivity.findViewHolderForAdapterPosition(position).NameOfYourViewInTheViewholder.setBackgroundColor((Color.parseColor("#336F0D")));

            for(int itemsSelect = 0; itemsSelect <= listaEmails.size() -1; itemsSelect++){

             listaItems  +=  "*"+listaEmails.get(itemsSelect).getDescripcion() + "\n";
            }

            itemsSeleccionados.setText("Items Seleccionados : "+  "\n" + listaItems);


        }


    }));

0
投票

我得到了这样的

public void onClick(View v){
        v.findViewById(R.id.textView).setBackgroundColor(R.drawable.selector_row);
 }

谢谢


-1
投票

我实现这一目的实际上是采用静态变量来存储RecyclerView中项目的最后点击位置,然后通知适配器更新最后点击位置的位置布局,即每当新位置时notifyItemChanged(lastClickedPosition)点击。在整个布局上调用notifyDataSetChanged()是非常昂贵且不可行的,因此仅针对一个位置执行此操作要好得多。

这是以下代码:

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

private String android_versionnames[];
private Context mContext;
private static lastClickedPosition = -1; // Variable to store the last clicked item position


    public RecyclerDataAdapter(Context context,String android_versionnames[]){
        this.android_versionnames = android_versionnames;
        this.mContext = context;
        }
    }


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

    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        holder.tv1.setText(android_versionnames[position]);    
        holder.itemView.setBackgroundColor(mContext.getResources().
        getColor(R.color.cardview_light_background));
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {                    
            v.setBackgroundColor(mContext.getResources().
            getColor(R.color.dark_background));
                if (lastClickedPosition != -1)
                    notifyItemChanged(lastClickedPosition);
                lastClickedPosition = position;
            }
        });
    }


    @Override
    public int getItemCount() {
        return android_versionnames.length;
    }


    public class ViewHolder extends RecyclerView.ViewHolder {
        private TextView tv1;

        public ViewHolder(final View itemView) {
            super(itemView);
            tv1=(TextView)itemView.findViewById(R.id.txtView1);
        }
    }
}

因此,我们实际上只会更新预期的项目,而不是对尚未更改的项目重新运行不必要的更新。


6
投票

实现这一目标的一个非常简单的方法是:

//instance variable
List<View>itemViewList = new ArrayList<>();

//OnCreateViewHolderMethod
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {    
    final View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_row, parent, false);
    final MyViewHolder myViewHolder = new MyViewHolder(itemView);

    itemViewList.add(itemView); //to add all the 'list row item' views

    //Set on click listener for each item view
    itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            for(View tempItemView : itemViewList) {
                /** navigate through all the itemViews and change color
                of selected view to colorSelected and rest of the views to colorDefault **/
                if(itemViewList.get(myViewHolder.getAdapterPosition()) == tempItemView) {
                    tempItemView.setBackgroundResource(R.color.colorSelected);
                }
                else{
                    tempItemView.setBackgroundResource(R.color.colorDefault);
                }
            }
        }
    });
    return myViewHolder;
}

UPDATE

上面的方法可能会破坏itemView的一些默认属性,在我的例子中,我使用的是CardView,并且卡片的角半径在点击时被移除。

更好的方案:

//instance variable
List<CardView>cardViewList = new ArrayList<>();

public class MyViewHolder extends RecyclerView.ViewHolder {
        CardView cardView; //THIS IS MY ROOT VIEW
        ...

        public MyViewHolder(View view) {
            super(view);
            cardView = view.findViewById(R.id.row_item_card);
            ...
        }
}

@Override
    public void onBindViewHolder(final MyViewHolder holder, int position) {
        final OurLocationObject locationObject = locationsList.get(position);
        ...

        cardViewList.add(holder.cardView); //add all the cards to this list

        holder.cardView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //All card color is set to colorDefault
                for(CardView cardView : cardViewList){
                cardView.setCardBackgroundColor(context.getResources().getColor(R.color.colorDefault));
                }
                //The selected card is set to colorSelected
                holder.cardView.setCardBackgroundColor(context.getResources().getColor(R.color.colorSelected));
            }
        });
}

更新2 - 重要

onBindViewHolder方法被多次调用,并且每次用户将视图滚动到视线之外并且回到视线中时!这将导致相同的视图多次添加到列表中,这可能会导致问题和代码执行的轻微延迟!

要解决这个问题,请更改

cardViewList.add(holder.cardView);

if (!cardViewList.contains(holder.cardView)) {
    cardViewList.add(holder.cardView);
}

5
投票

我可以建议我在我的应用程序中使用的这个解决方案。我已将此onTouchListener代码放在我的ViewHolder类的构造函数中。 itemView是构造函数的参数。请务必在此方法上使用return false,因为这需要使用OnClickListener

itemView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_DOWN)
        {
            v.setBackgroundColor(Color.parseColor("#f0f0f0"));
        }
        if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL)
        {
            v.setBackgroundColor(Color.TRANSPARENT);
        }
        return false;
    }
});

2
投票

在Drawable文件夹中创建Drawable文件

<item android:drawable="@color/SelectedColor" android:state_pressed="true"></item>
<item android:drawable="@color/SelectedColor" android:state_selected="true"></item>
<item android:drawable="@color/DefultColor"></item>

并在xml文件中

android:background="@drawable/Drawable file"

在RecyclerView onBindViewHolder中

holder.button.setSelected(holder.button.isSelected()?true:false);

喜欢切换按钮


2
投票

如果你使用kotlin,它真的很简单。

在您的RecyclerAdapter类中

userV.invalidateRecycler()

holder.card_User.setCardBackgroundColor(Color.parseColor("#3eb1ae").withAlpha(60))

在您的片段或活动中

 override fun invalidateRecycler() {
    if (v1.recyclerCompanies.childCount > 0) {
        v1.recyclerCompanies.childrenRecursiveSequence().iterator().forEach { card ->
            if (card is CardView) {
                card.setCardBackgroundColor(Color.WHITE)
            }
        }
    }
}

1
投票

我的解决方案

public static class SimpleItemRecyclerViewAdapter
        extends RecyclerView.Adapter<SimpleItemRecyclerViewAdapter.ViewHolder> {

    private final MainActivity mParentActivity;
    private final List<DummyContent.DummyItem> mValues;
    private final boolean mTwoPane;
    private static int lastClickedPosition=-1;
    **private static View viewOld=null;**
    private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            DummyContent.DummyItem item = (DummyContent.DummyItem) view.getTag();
            if (mTwoPane) {
                Bundle arguments = new Bundle();
                arguments.putString(ItemDetailFragment.ARG_ITEM_ID, item.id);
                ItemDetailFragment fragment = new ItemDetailFragment();
                fragment.setArguments(arguments);
                mParentActivity.getSupportFragmentManager().beginTransaction()
                        .replace(R.id.item_detail_container, fragment)
                        .commit();
            } else {
                Context context = view.getContext();
                Intent intent = new Intent(context, ItemDetailActivity.class);
                intent.putExtra(ItemDetailFragment.ARG_ITEM_ID, item.id);

                context.startActivity(intent);
            }

            **view.setBackgroundColor(mParentActivity.getResources().getColor(R.color.SelectedColor));
            if(viewOld!=null)
                viewOld.setBackgroundColor(mParentActivity.getResources().getColor(R.color.DefaultColor));
            viewOld=view;**
        }
    };

viewOld在开始时是null,然后指​​向最后选择的视图。使用onClick,您可以更改所选视图的背景,并重新定义所选倒数第二个视图的背景。简单而实用。


0
投票

在Drawable文件夹中创建一个选择器:

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

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

将属性添加到xml中(您声明RecyclerView):

android:background="@drawable/selector"

0
投票

在RecyclerView适配器的.onBindViewHolder()中添加项目视图的单击侦听器。获取当前选定的位置,并通过.setBackground()为先前选择的当前项目更改颜色


0
投票

从我这边最简单的方法是在adapterPage中添加一个变量作为最后点击的位置。

在onBindViewHolder中粘贴此代码,该代码检查与加载位置匹配的最后存储位置常量是我声明我的全局变量的类

if(Constants.LAST_SELECTED_POSITION_SINGLE_PRODUCT == position) {

    //change the view background here
    holder.colorVariantThumb.setBackgroundResource(R.drawable.selected_background);
}

//on view click you store the position value and notifyItemRangeChanged will 
// call the onBindViewHolder and will check the condition

holder.itemView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view){
        Constants.LAST_SELECTED_POSITION_SINGLE_PRODUCT=position;
        notifyItemRangeChanged(0, mColorVariants.size());
    } 
});
© www.soinside.com 2019 - 2024. All rights reserved.