Solved issue, Recycler View changes the views when scrolling.

I’ve met this problem with Recycler View. When I update a view, like changing the CheckBox, SwitchCompat, change the background color of view etc. After that when I scroll down or go up the view back to its normal position like the changes that I made it’s gone from view. It is because RecyclerView recycles every view which is not visible to the user. So, when the user scrolls back it recycles the previous view which is in normal form.

So, today I’m going to explain how we can save the view state.

The following shows the model we’re going to use in this example.

public class BookModel {

    private String bookName;
    private boolean wantToReadFlag;
    private int backgroundColor;

    public BookModel(String bookName) {
        this.bookName = bookName;
        wantToReadFlag = false;
        backgroundColor = Color.Grey;
    }

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public boolean isWantToReadFlag() {
        return wantToReadFlag;
    }

    public void setWantToReadFlag(boolean wantToReadFlag) {
        this.wantToReadFlag = wantToReadFlag;
    }
    
    public void setBackgroundColor(int backgroundColor){
        this.backgroundColor = backgroundColor;
    }
    
    public int getBackgroundColor(){
        return backgroundColor;
    }

    @Override
    public String toString() {
        return "BookModel{" +
                "bookName='" + bookName + '\'' +
                ", wantToReadFlag=" + wantToReadFlag +
                '}';
    }
}

The bookName is named for the book which we’re showing. The wantToReadFlag is for CheckBox, when the user checked checkBox we store a true value to model.

Below is code for RecyclerViewAdapter.

public class BookAdapter extends RecyclerView.Adapter<BookAdapter.MyViewHolder> {

    private final LayoutInflater layoutInflater;
    private List<BookModel> bookModels;

    public BookAdapter(List<BookModel> bookModels, final Context context) {
        this.bookModels = bookModels;
        this.layoutInflater = LayoutInflater.from(context);
    }

    @NonNull
    @Override
    public BookAdapter.MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new MyViewHolder(layoutInflater.inflate(R.layout.book_single_view, parent, false));
    }

    @Override
    public void onBindViewHolder(@NonNull BookAdapter.MyViewHolder holder, int position) {
        BookModel bookModel = bookModels.get(position);
        holder.bookNameTextView.setText(bookModel.getBookName());
        if (bookModel.isWantToReadFlag())     
            holder.wantToReadCheckBox.setChecked(true);
        else
            bookModel.setWantToReadFlag(false);
        holder.setICheckChangeListener(new ICheckChangeListener() {
            @Override
            public void onItemChecked(int position, boolean value) {
                bookModels.get(position).setWantToReadFlag(value);
            }
        });
    }

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

    class MyViewHolder extends RecyclerView.ViewHolder {

        private TextView bookNameTextView;
        private CheckBox wantToReadCheckBox;
        private ICheckChangeListener iCheckChangeListener;

        private MyViewHolder(View itemView) {
            super(itemView);
            bookNameTextView = itemView.findViewById(R.id.bookNameTextView);
            wantToReadCheckBox = itemView.findViewById(R.id.wantToReadCheckBox);
            wantToReadCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                    iCheckChangeListener.onItemChecked(getAdapterPosition(), b);
                }
            });
        }

        void setICheckChangeListener(ICheckChangeListener iCheckChangeListener) {
            this.iCheckChangeListener = iCheckChangeListener;
        }
    }
}

In onBindViewHolder, we have a setOnCheckChangeListener method which is called every time when user change CheckBox.  So, when it is called we stored a flag value in our BokkModel class. Now when the user scrolls bottom or comes back to the previous position the view never changes.

You can also add ClickListener on itemView when the user taps on the row you can change the background color and store in the model.

The following example shows how you can store the state of view with the background color. I’m only implementing the onBindView method.

@Override
public void onBindViewHolder(@NonNull BookAdapter.MyViewHolder holder, int position) {
    BookModel bookModel = bookModels.get(position);
    holder.itemView.setBackgroundColor(bookModel.getBackgroundColor());
    holder.bookNameTextView.setText(bookModel.getBookName());
    if (bookModel.isWantToReadFlag())     
        holder.wantToReadCheckBox.setChecked(true);
    else
        bookModel.setWantToReadFlag(false);
    holder.setICheckChangeListener(new ICheckChangeListener() {
        @Override
        public void onItemChecked(int position, boolean value) {
            bookModels.get(position).setWantToReadFlag(value);
        }
    });
     holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            bookModels.get(position).setBackgroundColor(Color.Red);
        }
    });
}

Below is the ICheckChangeListener interface.


public interface ICheckChangeListener {

    void onItemChecked(int position, boolean value);
}

That’s the interface which we implemented in our ViewHolder class.

See the complete example on GitHub.

Download Complete Code

That’s it now the view never changes it states on the scroll.

I hope this blog gives you a good understanding of RecyclerView. If you’ve any queries please do comment below.

 

You might be interested in: Beautiful Login Screen For Android With Example

or Basic Animation Of Android Views With Example

LEAVE A REPLY

Please enter your comment!
Please enter your name here