Search code examples
androidlistviewandroid-adapterview

Reset background color in Android ListView


In my QuestionsActivity, I am showing a question and bunch of answers. The question is displayed on TextView and answers are displayed on ListView that is composed of TextViews. There is an ActionButton named "Check Answer" and when it is clicked, it shows the correct answer by changing the background color of the TextView in the ListView.

The background changing code looks like this:

if (allAnswers.get(i).isCorrect())
{
   mAnswerList.getChildAt(i).setBackgroundColor
               (getResources().getColor(R.color.correct_answer_background));
   return;
}

and now there are two Buttons at the footer section of this QuestionsActivity called PreviousQuestionButton and NextQuestionButton and they are basically navigation buttons between questions.

The problem is, when I go to the next question after clicking on "Check Answer" button, the answer background color doesn't go away and remains in the next question answer options. I tried invalidate(), refreshDrawableState() method of ListView but no luck!

This is the method which displays the answers for a given question:

private void showAnswers(int questionLocation)
{
    int questionId = mAllQuestions.get(questionLocation).getQuestionId();
    List<Answer> answers = mAnswerRepository.getAllByQuestionId(questionId);

    mAnswerAdapter.clear();

    for (int i = 0; i < answers.size(); i++)
    {
        mAnswerAdapter.add(mOptionLetters[i] + ". "
                + answers.get(i).getAnswerText());
    }

    mAnswerAdapter.notifyDataSetChanged();
}

My Question

What I want is that when I click on next or previous buttons, the background color of the correct answer in ListView should disappear so that next and previous question button can show non-selected answer options list to the user. Is there any method which resets ListView to a state which does not have any background applied?

For selected answer option, I am using mAnswerList.clearChoices() in order to unselect but it does not apply for correct answer background color.


Solution

  • Well, to reset the color you can very well hard-reset the adapter by creating a new one. So don't clear and add as that may keep the views in the state they were before. I am not too sure about this since I am not clearing or adding from an adapter, but always creating a new one to fulfill my new needs.

    Anyway, another reason why things may not go in the direction you want is that the views may get recycled, since we're talking about a ListView. So if you want to highlight a list item, you should keep in the data model the information about highlight by initializing it to false and if the user selects one set the highlight state to true. I suppose the Answer class has as a minimum the following:

    public class Answer {
        private String data;
        private boolean correct;
    
        public String getData() {
            return data;
        }
    
        public boolean isCorrect() {
            return correct;
        }
    
        @Override
        public String toString() {
            return data;
        }
    
    }
    

    So your adapter could look close to this - getView method is the most important to notice (don't forget to set to default background if the answer is incorrect or the adapter should not highlight correct answer):

    public class MyAdapter extends ArrayAdapter<Answer> {
        private boolean showCorrectAnswer;
    
        private List<Answer> modelAnswers;
        public MyAdapter(Context context, List<Answer> answers) {
            super(context, android.R.layout.simple_list_item_1, answers);
            this.modelAnswers = answers;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View view = super.getView(position, convertView, parent);
            if(showCorrectAnswer && modelAnswers.get(position).isCorrect()) {
                view.setBackgroundColor(getContext().getResources().getColor(R.color.correct_answer_background));
            } else {
                view.setBackgroundColor(getContext().getResources().getColor(R.color.default_background));
            }
        }
    
        public void setShowCorrectAnswer(boolean showCorrectAnswer) {
            this.showCorrectAnswer = showCorrectAnswer;
            notifyDataSetChanged();
        }
    }
    

    What you need to do is to keep a reference to this custom adapter and if you need to highlight the correct answer or not simply call setShowCorrectAnswer(true / false);. It will trigger a redraw and in the getView() it will decide what to do based on adapter state and correct answer.

    Hope it make sense ... I wrote all this while drinking a beer :)