Question

I have an ArrayAdapter class that creates comment boxes. There is a button within the comment box that will be either blue or black. The color of the button is dependent on an array which is received through JSON. If the array looks like this "NO","NO","YES","NO","NO","NO" the third button will have blue text. My JSON and ArrayAdapter class create 7 comment boxes at a time. The problem is once the code changes a button to blue it continuously changes the button blue. By this I mean if an array is received that looks like this "NO","NO","YES","NO","NO","NO" the third button will be blue, then I receive another set of comments so this time the array looks like this "NO","NO","NO","NO","NO","NO" according to this code no button should be blue, but for some reason the third button is still blue. I could load multiple more sets of comments and the third button will always be blue even though the code clearly says it should be black. Strangely the button will be blue but will act as if it were a black button. Here is my ArrayAdapter,

class ListAdapter extends ArrayAdapter<Item> {
        public ListAdapter(Context context, int textViewResourceId) {
            super(context, textViewResourceId);
        }

        private List<Item> items;

        public ListAdapter(Context context, int resource, List<Item> items) {
            super(context, resource, items);
            this.items = items;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View v = convertView;
            if (v == null) {
                LayoutInflater vi;
                vi = LayoutInflater.from(getContext());
                v = vi.inflate(R.layout.list_item_layout, null);
            }
            final Item p = items.get(position);
            if (p != null) {
                //set xml objects 
                //must be done inside of class
              ButtonListViewItem = (TextView) v.findViewById(R.id.button_listview_item);
                if(p.getJSONArray().equals("NO")){
                 ButtonListViewItem.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        ButtonListViewItem.setTextColor(0xff000000);
                        new AsyncTask().execute();
                    }//end on click
                });
                }//end if equals NO
                if(p.getJSONArray().equals("YES")){
                    ButtonListViewItem.setClickable(false);
                    ButtonListViewItem.setTextColor(0xff3399FF);
                }//end if equals yes
            }//end if null
            return v;
        }//end getView
      }//end ListAdapter class
Was it helpful?

Solution

The text color is wrong because you're not correctly handling recycled views.

The shortest and simplest solution is to remove this check:

if (v == null)

and inflate a new view every time. This is less efficient, but will make your code easier to work with.

The solution if you opt to continue using recycled views is to explicitly set the text color and clickability of the button every time:

if (p.getJSONArray().equals("YES")) {
    ButtonListViewItem.setClickable(false);
    ButtonListViewItem.setTextColor(0xff3399FF);
} else {
    ButtonListViewItem.setClickable(true);
    ButtonListViewItem.setTextColor(0xff000000);
}

The reason you need to do that is because recycled views are handed over just as you left them, changed attributes and all. They will no longer match your XML layout. So when a view that was previously tied to a "YES" is recycled, the changes you made to the text color will still be in place: the text will be blue and the button won't be clickable.

Inflating a new view allows you start in a known state every time---you'll always have something that starts off matching your XML. The tradeoff is efficiency, inflating views is relatively expensive. If your apps needs to be more efficient you should look into the view holder pattern as well, as finding views is also an expense that can be avoided.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top