-1

I have a tasks app where the person can click on the checkbox of the task and the colour of the task will change. But i'm having a problem with binding this condition with the view. When the checkbox is checked, the colour changes but when the app is closed and opened again, the checkbox is not checked and the color goes back to normal. How can i retain the checked state of the checkbox and the text colour in this case.

Picture 1
Picture 2
Picture 3

My Adapter class -

 public void onBindViewHolder(@NonNull TaskHolder holder, int position) {
    Task currentTask = tasks.get(position);
    holder.a_tname.setText(currentTask.getTname());
    holder.a_tdate.setText(currentTask.getTDate());
    holder.a_ttime.setText(currentTask.getTTime());
    holder.a_tprior.setText(currentTask.getTprior());
    holder.bind(tasks.get(position));
    holder.checkbox.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            holder.bind2(tasks.get(position));
        }
    });
}
 class TaskHolder extends RecyclerView.ViewHolder  {
    private final TextView a_tname;
    private final TextView a_tdate;
    private  final TextView a_ttime;
    private final TextView a_tprior;
    ImageView priorityIndicator;
    CheckBox checkbox;


    public TaskHolder(View itemView) {
        super(itemView);
        a_tname = itemView.findViewById(R.id.a_tname);
        a_tdate=itemView.findViewById(R.id.a_tdate);
        a_ttime = itemView.findViewById(R.id.a_ttime);
        a_tprior = itemView.findViewById(R.id.a_tprior);
        priorityIndicator = itemView.findViewById(R.id.priorityIndicator);
        checkbox = itemView.findViewById(R.id.checkbox);

private void bind2(Task task){
        if(checkbox.isChecked()){
            int checkedtext = ContextCompat.getColor(a_tname.getContext(), R.color.grey);
            a_tname.setTextColor(checkedtext);
            int checkeddate =  ContextCompat.getColor(a_tdate.getContext(), R.color.grey);
            a_tdate.setTextColor(checkeddate);
            int checkedtime = ContextCompat.getColor(a_ttime.getContext(), R.color.grey);
            a_ttime.setTextColor(checkedtime);
            Toast.makeText(checkbox.getContext(), "Way to go! Now swipe to delete", Toast.LENGTH_LONG).show();
        }
        if(!checkbox.isChecked()){
            int untext = ContextCompat.getColor(a_tname.getContext(), R.color.black);
            a_tname.setTextColor(untext);
            int undate = ContextCompat.getColor(a_tdate.getContext(), R.color.black);
            a_tdate.setTextColor(undate);
            int untime = ContextCompat.getColor(a_ttime.getContext(), R.color.black);
            a_ttime.setTextColor(untime);
        }
    }

May i please know how this can be done

Omar Shawky
  • 1,242
  • 1
  • 12
  • 25
Harshitha
  • 29
  • 5
  • 1
    You need to save the state of the checkbox in your model class when you are selecting the checkbox. – akhil nair Sep 28 '21 at 10:33
  • Like @akhilnair has said. You need a boolean value in your model. which is set with your bind2 method. Then again in your onBindViewHolder you need to assign it to the checkbox. holder.checkbox.setChecked(currentTask.booleanValue); – Mark Vance Sep 28 '21 at 10:40
  • Thank you, but my checkbox is attached to the item layout of recycler view. How do I save that in my model class? – Harshitha Sep 28 '21 at 12:02
  • Can you elaborate on your answer, I am quite new to android and it would be pretty helpful. – Harshitha Sep 28 '21 at 12:09

1 Answers1

0

Because after closing and opening of your app, your Fragment/Activity calls onCreate again (which follows with the normal lifecycle of fragment methods') creating the fragment from zero, what you need is to store UI data somewhere before closing the app and fetch it later everytime onViewCreated is called, you can store your data in SharedPreferences or using a database like SQLite, Room Database or Firebase.

incase of SharedPreferences I can give you a quick example on how to use it but I highly recommend you start learning about Room database in case if the data you want to store would be like data structures, then Room will provide you with good ways to store and retrieve your data through what it calls entities.

  1. first, you should get a reference to your SharedPreferences (you can name it anything instead of 'recycleview')
SharedPreferences shared = getContext().getSharedPreferences("recycleview",Context.MODE_PRIVATE);
SharedPreferences.Editor editor = shared.edit();
//when you need to store that a certain item got checked, might put it's position as key
String posString = Integer.valueOf(position).toString();
editor.putBoolean("item" + posString ,checkbox.isChecked).apply();
  1. and next time when you start the application, when you assign the data to your Adapter, when you bind your view holder to the data, check if there's an old value stored in the sharedPreferences like this :
SharedPreferences shared = context.getSharedPreferences("recycleview",Context.MODE_PRIVATE);
String keyString = Integer.valueOf(position).toString();
checkbox.setChecked(shared.getBoolean("item" + keyString ,false ));

where if the SharedPreferences didn't find a certain key stored in it, it returns the default value that you specified as second parameter to the method getBoolean (which in this case false).

  • you can start reading about Room database from here :

Accessing data using Room Database| Android Developers

  • you can start reading about SharedPerfreneces from here :

Save key-value data |Android Developers


Update

yes I see it belongs to the recycle view items that's why I said to store it with a key named 'item' + its position string.

  • if your recycler view data is an entity or defined by a unique key and you want to resort to a more complicate way of recycler view selection you can check my other answer here.

  • in the previously mentioned answer, when you're finished with your fragment you would call tracker.getSelection() and check which keys got selected to store them in your database.

  • when you come back to this fragment, you will get what you stored in your database and call tracker.select(key) on all of them, where when the adapter comes to bind some data you would ask it if tracker.isSelected(data.get(i).getKey()) and set the checkbox by the returned boolean value as an example.

  • if you still willing to use the SharedPreferences, you could add an onClickListener to the holder rootView, whenever the user click anywhere in the holder it shall trigger this onClickListener to check its position by using the method holder.getAbsoluteAdapterPosition and using this returned position you would store whether the checkbox is currently checked or not .

public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
    SharedPreferences shared ;
    SharedPreferences.Editor editor;
 //pass the to the constructor a reference to the SharedPreferences from the Fragment/Activity
    public MyAdapter(SharedPreferences shared, ...other paramters) {
        this.shared= shared;
        this.editor = shared.edit();
    }
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
         View v = LayoutInflater.from(context).inflate(R.layout.recycler_view_item, parent, false);
         View root = v.getRootView();
         MyViewHolder holder = new MyViewHolder (root);
     root.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = holder.getAbsoluteAdapterPosition();
                //when you need to store that a certain item got checked, might put it's position as key
                String posString = Integer.valueOf(position).toString();
                editor.putBoolean("item" + posString, holder.getcheckbox().isChecked).apply();
            }
        });
        return root ;
    }
    
    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        ...
        boolean isSelected = shared.getBoolean("item" + position,false )
        Checkbox checkbox = holder.getcheckbox();
        checkbox.setChecked(isSelected);
    }
    ...
}

where holder.getcheckbox() is a method in the view holder that should return the checkbox view

Omar Shawky
  • 1,242
  • 1
  • 12
  • 25
  • Thank you for your answer. I am using Room database to store the tasks but the checkbox is attached to the item layout of the recycler view. What should I do in this case? – Harshitha Sep 28 '21 at 12:03
  • check my update see if it fits your criteria – Omar Shawky Sep 28 '21 at 13:41
  • Your code definitely worked, thank you. But I encountered a problem with it - when I delete the checked item, the item below it(unchecked) gets checked because it takes up the previous item's place. May I know how to resolve it. The detailed question is here - https://stackoverflow.com/q/69690827/16983680 – Harshitha Oct 24 '21 at 10:49