recyclerview item change android background android-recyclerview

android - change background item recyclerview



Cambiar el color de fondo del elemento seleccionado en la vista de reciclaje (12)

¿Cómo cambiar el color de fondo de solo la vista seleccionada en mi ejemplo de vista de reciclaje? Solo se debe cambiar el color de fondo de la vista del elemento seleccionado. Solo se debe mostrar un elemento seleccionado con cambio de color de fondo a la vez y el resto debe ser como antes de seleccionar. Aquí está mi código:

Actividad principal

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


Agregue escucha de clics para ver el elemento en .onBindViewHolder () del adaptador de RecyclerView. obtener la posición seleccionada actualmente y cambiar el color por .setBackground () para el elemento seleccionado previamente y actual


Crear archivo dibujable en el plegador 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>

Y en archivo xml

android:background="@drawable/Drawable file"

En RecyclerView onBindViewHolder

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

Me gusta botón de alternar


Cree un selector en la carpeta 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>

Agregue la propiedad a su xml (donde declara RecyclerView):

android:background="@drawable/selector"


Finalmente obtuve la respuesta.

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

aquí ''row_index'' se establece como ''-1'' inicialmente

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


La forma más simple desde mi lado es agregar una variable en la página del adaptador como la última posición en la que se hizo clic.

en onBindViewHolder pegue este código que verifica la última posición almacenada que coincida con las posiciones de carga Constantes es la clase donde declaro mis variables globales

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


Lo que hice para lograr esto fue tomar una variable estática para almacenar la última posición en la que se hizo clic en el elemento en RecyclerView y luego notificar al adaptador para actualizar el diseño en la posición en la última posición en la que se hizo clic, es decir, notificarItemChanged (lastClickedPosition) cada vez que una nueva posición se hace clic Llamar a notifyDataSetChanged () en todo el diseño es muy costoso e inviable, por lo que hacer esto solo para una posición es mucho mejor.

Aquí está el código para esto:

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

Por lo tanto, en realidad actualizaremos solo el elemento deseado y no volveremos a ejecutar actualizaciones innecesarias de los elementos que ni siquiera se han cambiado.


Lo tengo asi

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

Gracias


Logré hacer esto desde mi Actividad donde configuro mi Rv y no desde el adaptador

Si alguien necesita hacer algo similar, aquí está el código

En este caso, el color cambia en un 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); } }));


Mi solución:

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 es null al principio, luego apunta a la última vista seleccionada. Con onClick cambia el fondo de la vista seleccionada y redefine el fondo de la penúltima vista seleccionada. Simple y funcional.


Puedo sugerir esta solución, que utilicé en mi aplicación. He colocado este código de onTouchListener en el constructor de mi clase ViewHolder. itemView es el argumento del constructor. Asegúrese de usar return false en este método porque esto necesita trabajar 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; } });


Si usas kotlin, es realmente simple.

En su clase RecyclerAdapter

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

En su fragmento o actividad

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


Una forma realmente simple de lograr esto sería:

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

ACTUALIZAR

El método anterior puede arruinar algunos atributos predeterminados del itemView, en mi caso, estaba usando CardView, y el radio de la esquina de la tarjeta se eliminaba al hacer clic.

Mejor solucion:

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

ACTUALIZACIÓN 2 - IMPORTANTE

El método onBindViewHolder se llama varias veces, ¡y también cada vez que el usuario desplaza la vista fuera de la vista y la vuelve a ver! ¡Esto hará que se agregue la misma vista a la lista varias veces, lo que puede causar problemas y retrasos menores en la ejecución del código!

Para arreglar esto, cambie

cardViewList.add(holder.cardView);

a

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