Venkat Maddy
Venkat Maddy

Reputation: 21

Android RecyclerView set selected item background

I am developing an android application in which I have a Horizontal Recyclerview holds text of 12 month names. When app opens, the current month background will change to red. Till here everything is working fine and as expected. Current behavior: Whenever I select the other month name, selected month name background color is changing to red successfully but previous selected month name background is not changing to white it still remains in red color. Expected behavior: Now Whenever I select the other month name, I need to change the background color of selected month name to red and previous selected month name background to white. below is my recyclerview adapter class code:

public class MonthNamesAdapter extends RecyclerView.Adapter<MonthNamesAdapter.MonthNameViewHolder> {

List<MonthNamesModel> monthNamesModelList;
MonthNamesModel monthNamesModel;
Context context;
int lastPosition = -1;
Calendar calendar;
int month, year, date;

String[] monthName = {"January", "February",
        "March", "April", "May", "June", "July",
        "August", "September", "October", "November",
        "December"};
String monthStr;

TextView monthNameTv, numberOfDaysTv;
LinearLayout monthNamesLinearLayout;


public MonthNamesAdapter(List<MonthNamesModel> monthNamesModelList, Context context) {
    this.monthNamesModelList = monthNamesModelList;
    this.context = context;
}

@Override
public MonthNameViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    calendar = Calendar.getInstance();
    month = calendar.get(Calendar.MONTH);
    monthStr = monthName[month];
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.month_name_list, parent, false);

    return new MonthNameViewHolder(view);
}

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


    monthNamesModel = monthNamesModelList.get(position);
    holder.monthNameTv.setText(monthNamesModel.getMonthName());
    holder.numberOfDaysTv.setText(monthNamesModel.getNumberOfDays());
    Log.d("MonthNameAdapter", "onBindViewHolder: Month Number"+month);

    holder.monthNamesLinearLayout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            lastPosition = position;
            notifyDataSetChanged();
        }
    });

    if (lastPosition == position){
        holder.monthNamesLinearLayout.setBackgroundColor(context.getResources().getColor(R.color.app_color));
        holder.numberOfDaysTv.setTextColor(context.getResources().getColor(R.color.colorPrimary));
        holder.monthNameTv.setTextColor(context.getResources().getColor(R.color.colorPrimary));

    }else{
        holder.monthNamesLinearLayout.setBackgroundColor(context.getResources().getColor(R.color.colorPrimary));
        holder.numberOfDaysTv.setTextColor(context.getResources().getColor(R.color.colorBlack));
        holder.monthNameTv.setTextColor(context.getResources().getColor(R.color.app_color));
    }

    if (lastPosition !=position){
        if (month == position){
            holder.monthNamesLinearLayout.setBackgroundColor(context.getResources().getColor(R.color.app_color));
            holder.numberOfDaysTv.setTextColor(context.getResources().getColor(R.color.colorPrimary));
            holder.monthNameTv.setTextColor(context.getResources().getColor(R.color.colorPrimary));

        }
    }

}

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

public class MonthNameViewHolder extends RecyclerView.ViewHolder {
    TextView monthNameTv, numberOfDaysTv;
    LinearLayout monthNamesLinearLayout;

    public MonthNameViewHolder(View itemView) {
        super(itemView);

        monthNameTv = itemView.findViewById(R.id.monthNameTv);
        numberOfDaysTv = itemView.findViewById(R.id.numberOfDaysTv);
        monthNamesLinearLayout = itemView.findViewById(R.id.monthNamesLinearLayout);

    }
}
}

Any help would be very grateful!!! Thanks in advance...

Upvotes: 1

Views: 933

Answers (5)

user4571931
user4571931

Reputation:

make one pojo class for two field month name and boolean for selected like below code ..

public class Month {
private String value;
public String getValue() {
    return value;
}

public void setValue(String value) {
    this.value = value;
}

private boolean selectedFlag;


public boolean isSelectedFlag() {
    return selectedFlag;
}

public void setSelectedFlag(boolean selectedFlag) {
    this.selectedFlag = selectedFlag;
}

}

then after make interface into adapter to handle click event for selected value like below..

   List<Month> mStringList = new ArrayList<>();// hear you can pass any pojo class object.
Context mContext;


    onItemClickListner onItemClickListner;

public void setOnItemClickListner(RecyclerViewAdpater.onItemClickListner onItemClickListner) {
    this.onItemClickListner = onItemClickListner;
}

public interface onItemClickListner {
    void onClick(Month str);//pass your object types.
}
    @Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
    Month data = mStringList.get(position); // if you pass object of class then create that class object.
    if (data.isSelectedFlag()){
        holder.textView.setBackgroundColor(Color.RED);
    }
    else{
        holder.textView.setBackgroundColor(Color.WHITE);

    }
    // below code handle click event on recycler view item.
    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            onItemClickListner.onClick(data);
        }
    });
}

then after define all Month name into Month class object and selected value false then object add into list and bind into adapter. after adapter bind into recycler view then called below code ..

recyclerViewAdpater.setOnItemClickListner(new RecyclerViewAdpater.onItemClickListner() {
        @Override
        public void onClick(Month str) {
            str.setSelectedFlag(true);
            recyclerViewAdpater.notifyDataSetChanged();
        }
    });

Upvotes: 0

Myself
Myself

Reputation: 168

Try this

Add an Interface

public interface PositionCallBack {
 void posChanged(int currentPos); //currentPos can also be boolean 
}

In ModelClass add one more string or boolean or int as "isSelected", Initialize first setIsSelected("0") in the MainActivity// if boolean set it as false

In the adapter class

 currentPos=Integer.parseInt(monthNamesModelList.get(position).getIsSelected());
    if (currentPos==1){
        holder.monthNamesLinearLayout.setBackgroundColor(context.getResources().getColor(R.color.colorRed));
    }else {
        holder.monthNamesLinearLayout.setBackgroundColor(context.getResources().getColor(R.color.colorWhite));
    }
    holder.monthNamesLinearLayout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            for (int i=0;i<monthNamesModelList.size();i++){
                MonthNames monthNames=new MonthNames();
                if (i==position){
                    monthNames.setIsSelected("1");
                }else {
                    monthNames.setIsSelected("0");
                }
                monthNames.setMonthNames(monthStrins[i]);
            }
            notifyDataSetChanged();
            notifyItemChanged(position);
            positionCallBack.posChanged(position);
        }

    });

In MainActivity

    monthNamess= new String[]{"January", "February",
            "March", "April", "May", "June", "July",
            "August", "September", "October", "November",
            "December"};

   Calendar calendar = Calendar.getInstance();
    int month = calendar.get(Calendar.MONTH);

    for (int i=0;i< monthNamess.length;i++){
        MonthNames monthNames=new MonthNames();
        if (i==month){

            monthNames.setIsSelected("1");
        }else {
            monthNames.setIsSelected("0");

        }
        monthNames.setMonthNames(monthNamess[i]);
        arrayList.add(monthNames);
    }

  RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(context,
            LinearLayoutManager.HORIZONTAL, false);
    recycler_view.setLayoutManager(mLayoutManager);

    monthNamesAdapter=new MonthNamesAdapter(arrayList,context,this,monthNamess);
    recycler_view.setAdapter(monthNamesAdapter);
    monthNamesAdapter.notifyDataSetChanged();

// Here arrayList is the list of Model Class

Implement the Interface in MainActivity

 @Override
public void posChanged(int currentPos) {
    arrayList=new ArrayList<>();
    for (int i=0;i<monthNamess.length;i++){
        MonthNames monthNames=new MonthNames();
        if (i==currentPos){

            monthNames.setCurrentPos("1");
        }else {
            monthNames.setCurrentPos("0");

        }
        monthNames.setMonthNames(monthNamess[i]);
        arrayList.add(monthNames);
    }
    monthNamesAdapter=new MonthNamesAdapter(arrayList,context,this,monthNamess);
    recycler_view.setAdapter(monthNamesAdapter);
    monthNamesAdapter.notifyDataSetChanged();
}

Upvotes: 1

Abu Yousuf
Abu Yousuf

Reputation: 6107

Set a default property to views and changed the property if that position satisfy your condition:

    //set a default property sot not selected state
    holder.monthNamesLinearLayout.setBackgroundColor(context.getResources().getColor(R.color.colorPrimary));
    holder.numberOfDaysTv.setTextColor(context.getResources().getColor(R.color.colorBlack));
    holder.monthNameTv.setTextColor(context.getResources().getColor(R.color.app_color));


    // if position satisfy you condition then set property for selected state.
    if (lastPosition == position ){
       holder.monthNamesLinearLayout.setBackgroundColor(context.getResources().getColor(R.color.app_color));
       holder.numberOfDaysTv.setTextColor(context.getResources().getColor(R.color.colorPrimary));
       holder.monthNameTv.setTextColor(context.getResources().getColor(R.color.colorPrimary));
    }else if( month == position){
       holder.monthNamesLinearLayout.setBackgroundColor(context.getResources().getColor(R.color.app_color));
       holder.numberOfDaysTv.setTextColor(context.getResources().getColor(R.color.colorPrimary));
       holder.monthNameTv.setTextColor(context.getResources().getColor(R.color.colorPrimary));
    }

I think this way you don't have to think complex way.

Edit:

You can make it more simple if you assign calendar.get(Calendar.MONTH); value to lastPosition initially. Then you can ignore month == position this condition if that didn't break you business logic.

Upvotes: 0

BiRjU
BiRjU

Reputation: 753

may be you can add one boolean variable in 'MonthNamesModel' with name isSelected

that will help with to maintain all you need just check that variable in onBindViewHolder

  if(monthNamesModel .getIsSelected())
   {holder.monthNamesLinearLayout.setBackgroundColor(context.getResources().getColor(R.color.app_color));
        holder.numberOfDaysTv.setTextColor(context.getResources().getColor(R.color.colorPrimary));
        holder.monthNameTv.setTextColor(context.getResources().getColor(R.color.colorPrimary));
 }else {holder.monthNamesLinearLayout.setBackgroundColor(context.getResources().getColor(R.color.colorPrimary));
        holder.numberOfDaysTv.setTextColor(context.getResources().getColor(R.color.colorBlack));
        holder.monthNameTv.setTextColor(context.getResources().getColor(R.color.app_color));
 }

and change that variable in

   holder.monthNamesLinearLayout.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {

      if( monthNamesModel .getIsSelected())
      {
      monthNamesModelList.get(position).setIsSelected(false);
      monthNamesModel .setIsSelected(false);
      }
      else
      {
      monthNamesModelList.get(position).setIsSelected(true);
      monthNamesModel .setIsSelected(true) ;
      }
        notifyDataSetChanged();
    }
});

Upvotes: 0

manhtuan21
manhtuan21

Reputation: 3455

Try this :

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

        monthNamesModel = monthNamesModelList.get(position);
        holder.monthNameTv.setText(monthNamesModel.getMonthName());
        holder.numberOfDaysTv.setText(monthNamesModel.getNumberOfDays());
        Log.d("MonthNameAdapter", "onBindViewHolder: Month Number"+month);

        if (lastPosition == position){
            holder.monthNamesLinearLayout.setBackgroundColor(context.getResources().getColor(R.color.app_color));
            holder.numberOfDaysTv.setTextColor(context.getResources().getColor(R.color.colorPrimary));
            holder.monthNameTv.setTextColor(context.getResources().getColor(R.color.colorPrimary));

        }else{
            holder.monthNamesLinearLayout.setBackgroundColor(context.getResources().getColor(R.color.colorPrimary));
            holder.numberOfDaysTv.setTextColor(context.getResources().getColor(R.color.colorBlack));
            holder.monthNameTv.setTextColor(context.getResources().getColor(R.color.app_color));
        }
        holder.monthNamesLinearLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                notifyDataSetChanged();
            }
        });

Upvotes: 0

Related Questions