Reset background color in Android ListView

2.8k views Asked by At

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.

5

There are 5 answers

3
gunar On BEST ANSWER

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 :)

0
AndroidHacker On

As per my understanding U need to change color of text view in one of the list view row i.e row containing correct answer.

If this is your problem then On Click of button simply clear list view and recreate list view. Not when list view is recreated then check out position of row which contains correct answer. After getting row position simply change color of text view.

For Ex: In your Adapter class check as fallows in your getView();

for ( int i = 0; i < position.length ; i++ )
{
if(position == your_required_position){
{
textview.setColor(Color.BLUE);
}else{
textview.setColor(Color.BLACK);
}
}
1
Infinite Recursion On

In the onClickListener of "Check Answer" button, you need to reset the color:

void onClick (View v){
    ..............
    mAnswerList.getChildAt(currentQuestion).setBackgroundColor
                   (getResources().getColor(R.color.default_answer_background));
}
0
Tom Tsagkatos On

you can save the default background somewhere, and when you press next/previous question button you should apply that color. Example:

TypedArray array = getTheme().obtainStyledAttributes(new int[] {  
    android.R.attr.colorBackground, 
    android.R.attr.textColorPrimary, 
}); 
int backgroundColor = array.getColor(0, 0xFF00FF); 
int textColor = array.getColor(1, 0xFF00FF); 
array.recycle();

I found this code online to get background and text color (you can just keep the background part), when the onClick activates just set the background of your view to "backgroundColor"

0
daemontus On

Basically, I agree with the answer from payeli - you should change the background of selected answer in the "next/previous question" button.

But then there is this question: "Is there any method which resets ListView to a state which does not have any background applied?"

Answer to this (as far as I know) is: not directly. But there are two workarounds.

If you call notfiyDataSetChange, not all views are completely redrawn. If possible, just the appropriate values are changed. It's mainly for performance reasons. (Imagine having 1000 contacts with images and names dumped and redrawn)

So how can you deal with this? (Other then reseting the background in the onClick method) Since you said these items are answers for a question, I assume you are not concerned about performance because there won't be too many of them.

Then you can simply:

A) Create new instance of Adapter instead of changing data in the old one. When you switch adapters, all views in list are removed, so, no recycling can happen in the new adapter.

B) Create custom Adapter, override getView method and make sure every time view is requested, you return a new view, so no recycling can happen.

Again: this really isn't "performance friendly" and should not be used with big lists with a lot of items!

If you want to know more, feel free to ask in comments or read the reference of Adapter class, especially the parameter convertView of getView method. (http://developer.android.com/reference/android/widget/Adapter.html)