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

时间:2016-11-19 11:12:51

标签: android background android-recyclerview

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

MainActivity

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*/

        }
    }
}

19 个答案:

答案 0 :(得分:82)

最后,我得到了答案。

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);
        }
    }

答案 1 :(得分: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;
}

<强>更新

上面的方法可能会破坏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);
}

答案 2 :(得分: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;
    }
});

答案 3 :(得分:2)

在Drawable foloder中创建可绘制文件     

<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);

喜欢切换按钮

答案 4 :(得分: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)
            }
        }
    }
}

答案 5 :(得分: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可以更改所选视图的背景,并重新定义所选倒数第二个视图的背景。 简单实用。

答案 6 :(得分:1)

对此有一个非常简单的解决方案,您不必在适配器中工作。要更改 RecyclerView 中点击项目的背景,您需要使用 iterface 捕捉适配器中的点击:

interface ItemClickListener {
    fun onItemClickListener(item: Item, position: Int)
}

当我们点击时,我们将获得项目和项目位置。在适配器中的绑定函数中,我们将设置点击监听器:

container.setOnClickListener {
    onClickListener.onItemClickListener(item, position)
}

在您的活动中,您将实现此接口:

class MainActivity : AppCompatActivity(), ItemAdapter.ItemClickListener {

接下来我们需要实现项目点击的背景变化逻辑。逻辑是这样的:当用户点击一个项目时,我们检查被点击项目的背景是否为白色(该项目之前没有被点击),如果这个条件为真,我们将改变该项目中所有项目的背景RecyclerView 为白色(如果有的话,使之前点击和标记的项目无效),然后将点击项目的背景颜色更改为青色以标记它。如果被点击的项目的背景是蓝绿色(这意味着用户再次点击之前标记的同一个项目),我们将所有项目的背景颜色更改为白色。首先,我们需要将我们的项目背景颜色作为 ColorDrawable。我们将使用迭代器函数遍历 RecyclerView 的所有项(子项),并使用 forEach() 函数更改每个项的背景。这个方法看起来像这样:

 override fun onItemClickListener(item: Item, position: Int) {
        val itemBackground: ColorDrawable =
            binding.recycler[position].background as ColorDrawable
        if (itemBackground.color == ContextCompat.getColor(this, R.color.white)) {
            binding.recycler.children.iterator().forEach { item ->
                item.setBackgroundColor(
                    ContextCompat.getColor(
                        this,
                        R.color.white
                    )
                )
            }
            binding.recycler[position].setBackgroundColor(
                ContextCompat.getColor(this, R.color.teal_200)
            )
        } else {
            binding.recycler.children.iterator().forEach { item ->
                item.setBackgroundColor(
                    ContextCompat.getColor(
                        this,
                        R.color.white
                    )
                )
            }
        }
    }

所以现在你改变了项目点击的背景,如果你点击同一个项目,你会把背景改回以前的样子。

答案 7 :(得分:0)

我设法从我设置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);


        }


    }));

答案 8 :(得分:0)

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

更改颜色

答案 9 :(得分: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());
    } 
});

答案 10 :(得分:0)

我是这样的

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

谢谢

答案 11 :(得分:0)

我的解决方案

在我的解决方案中,我不使用notifyDataSetChanged(),因为每当单击项目时都会烦人,列表中的所有项目都会刷新。为了解决这个问题,我使用了notifyItemChanged(position);。这只会更改所选的项目。

下面,我添加了omBindViewHolder的代码。

private int previousPosition = -1;
private SingleViewItemBinding previousView;

@Override
public void onBindViewHolder(@NonNull final ItemViewHolder holder, final int position) {
    holder.viewBinding.setItem(itemList.get(position));
    holder.viewBinding.rlContainerMain.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            clickRecyclerView.clickRecyclerItem(position, 0);

            previousPosition = position;
            notifyItemChanged(position);

            if(previousView != null){
                previousView.rlContainerMain.setBackgroundColor(
                        ContextCompat.getColor(context, R.color.colorGrayLight));

            }
        }
    });

    if(position == previousPosition){
        previousView = holder.viewBinding;

        holder.viewBinding.rlContainerMain.setBackgroundColor(
                ContextCompat.getColor(context, R.color.colorPrimary));

    }
    else {
        holder.viewBinding.rlContainerMain.setBackgroundColor(
                ContextCompat.getColor(context, R.color.colorGrayLight));

    }

}

答案 12 :(得分:0)

我能够这样更改选定的视图颜色。我认为这是简单的方法(因为您不必创建布局和变量的实例。

请确保您没有在回收视图的标签中提供任何背景色。

holder.itemView.setBackgroundColor(Color.parseColor("#8DFFFFFF"));

onBindViewHolder()方法在下面给出

@Override
public void onBindViewHolder(@NonNull final MyViewHolder holder, final int position) {

        holder.item_1.setText(list_items.get(position).item_1);
        holder.item_2.setText(list_items.get(position).item_2);
        holder.select_cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

                if (isChecked){

                    holder.itemView.setBackgroundColor(Color.parseColor("#8DFFFFFF"));
                }else {

                    holder.itemView.setBackgroundColor(Color.parseColor("#FFFFFF"));
                }
            }
        });
}

答案 13 :(得分:0)

在Kotlin中,您可以简单地做到这一点: 您所需要做的就是创建一个像这样的静态变量:

companion object {
     var last_position = 0
}

然后在您的 onBindViewHolder 中添加以下代码:

holder.item.setOnClickListener{
        holder.item.setBackgroundResource(R.drawable.selected_item)
        notifyItemChanged(last_position)
        last_position=position
    }

哪个项目是recyclerView的子项目,您要在单击后更改其背景。

答案 14 :(得分:0)

在适配器类中,将 Integer 变量设置为 index 并将其分配为“ 0”(如果要默认选择第一项,则不分配“ -1” ”)。然后使用您的 onBindViewHolder 方法

@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) {
    holder.texttitle.setText(listTitle.get(position));
    holder.itemView.setTag(listTitle.get(position));
    holder.texttitle.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            index = position;
            notifyDataSetChanged();
        }
    });
    if (index == position)
        holder.texttitle.setTextColor(mContext.getResources().getColor(R.color.selectedColor));
    else
        holder.texttitle.setTextColor(mContext.getResources().getColor(R.color.unSelectedColor));
}

就是这样,您很高兴。在如果条件为true的情况下,将放置您选择的颜色或所需的颜色,否则将未选择的颜色放置在该颜色的任何位置。

答案 15 :(得分:0)

我在Kotlin中实现了该实现,虽然效率不是很高,但是可以 ivIsSelected是一个ImageView,在我的情况下代表一个选中标记

var selectedItems = mutableListOf<Int>(-1)

override fun onBindViewHolder(holder: ContactViewHolder, position: Int) {
    // holder.setData(ContactViewModel, position)  // I'm passing this to the ViewHolder
    holder.itemView.setBackgroundColor(Color.WHITE)   
    holder.itemView.ivIsSelected.visibility = INVISIBLE
    selectedItems.forEach {
        if (it == position) {
            holder.itemView.setBackgroundColor(Color.argb(45, 0, 255, 43))
            holder.itemView.ivIsSelected.visibility = VISIBLE
        }
    }

    holder.itemView.setOnClickListener { it ->
        it.setBackgroundColor(Color.BLUE)  
        selectedItems.add(position)
        selectedItems.forEach { selectedItem ->  // this forEach is required to refresh all the list
            notifyItemChanged(selectedItem)
        }

    }
}

答案 16 :(得分: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"

答案 17 :(得分:-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);
        }
    }
}

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

答案 18 :(得分:-2)

я не знаю на сколько это поможет но я типа так сделал:) в адаптере @Override public void onBindViewHolder(@NonNull NoteViewHolderholder) (@NonNull NoteViewHolderholder); holder.itemView.setBackgroundResource(R.drawable.bacground_button); }