ViewHolder is not a good place to store data state - as you are doing.

A ViewHolder is not associated with the data item, it's associated with the item layout, and when recycling happens, the view holder is also affected.

You need to store selection state in MyObject, so it's completely separate from the list item views. With that done, you'll be able to count on selection state being correct when updating the UI (the check box). Make sure to update selection state in an appropriate MyObject based on user actions.

-- Kostya

26.02.2011 5:00, Wall-E пишет:
I have a ListActivity and an ArrayAdapter that contains a list of an
Object for example ArrayAdapter<MyObject>.  Now in my ArrayAdapter I
inflate a layout that includes a checkbox.  I'm having the issue now
that when I click on the checkboxes it's fine until it scrolls past
the window.  Now I know that the adapter recycles views so let me
explain how I have my adapter set up and if anyone could kindly see
what I'm doing wrong:

I have a ViewHolder class such as the following:

         public class ViewHolder
        {
                View base;
                CheckBox checkbox;
                TextView tagTexView;
                TextView tagIDTextView;

                public ViewHolder(View base)
                {
                        this.base = base;
                }

                CheckBox getTagCheckBox()
                {
                        if(checkbox == null)
                        {
                                checkbox = (CheckBox) 
base.findViewById(R.id.tagInfoCheckBox);
                        }
                        return checkbox;
                }

                TextView getTagMainIdentifierTextView()
                {
                        if(tagTexView == null)
                        {
                                TwoLineListItem twoListItem = (TwoLineListItem)
base.findViewById(R.id.taginfo_layoutTwoLineListItem);
                                tagTexView = (TextView) twoListItem.getText1();
                        }
                        return tagTexView;
                }

                TextView getTagIDTextView()
                {
                        if(tagIDTextView == null)
                        {
                                TwoLineListItem twoListItem = (TwoLineListItem)
base.findViewById(R.id.taginfo_layoutTwoLineListItem);
                                tagIDTextView = (TextView) 
twoListItem.getText2();
                        }
                        return tagIDTextView;
                }
        }

Now in my getView method, I inflate convertView and create the
viewHolder if convertView is null or set the view holder if it's not
(holder = (ViewHolder) convertView.getTag()).

After that, I set all the values of the views by accessing the views
using the holder, for example:

holder.getTagCheckBox().setChecked(tag.plot);

where tag is MyObject that I get using getItem(position) inside my
getView and tag.plot is the boolean value that will indicate if the
checkbox should be checked or not.

I also created a OnCheckedChangeListener that just sets to tag.plot to
whatever the checked state is and then call notifyDataSetChanged();

So the text that I update in my views works just fine but the checkbox
seems to get screwed up and although I've read a few suggestions, none
of them have worked.

        @Override
        public View getView(final int position, View convertView, ViewGroup
parent)
        {
                mInflater = LayoutInflater.from(context);

                final MyObject tag = this.getItem(position);

                // A ViewHolder keeps references to children views to avoid
                // unneccessary calls to findViewById() on each row.
                ViewHolder holder;

                // When convertView is not null, we can reuse it directly, 
there is
                // no need to reinflate it. We only inflate a new View when the
convertView
                // supplied by ListView is null.
                if (convertView == null)
                {
                        convertView = 
mInflater.inflate(R.layout.taginfo_layout, null);

                        // Creates a ViewHolder and store references to the two 
children
                        // views we want to bind data to.
                        holder = new ViewHolder(convertView);

                        convertView.setTag(holder);
                }
                else
                {
                        // Get the ViewHolder back to get fast access to the 
TextView
                        // and the ImageView.
                        holder = (ViewHolder) convertView.getTag();
                }

                // Set the checkbox value to the value of tag.plot
                holder.getTagCheckBox().setChecked(tag.plot);
                holder.getTagCheckBox().setOnCheckedChangeListener(new
android.widget.CompoundButton.OnCheckedChangeListener()
                {
                        @Override
                        public void onCheckedChanged(CompoundButton buttonView,
                                        boolean isChecked)
                        {
                                tag.plot = isChecked;
                                notifyDataSetChanged();
                        }

                });

                 // just for testing I print out the position of the
view
                holder.getTagMainIdentifierTextView().setText("Position: " +
position);

                holder.getTagIDTextView().setText("Tag ID: " + tagid);

                return convertView;
        }

If anyone could find what my mistake is in terms of handling the
checkbox, I would greatly appreciate it.  Also let me know if I need
to post more code.



--
Kostya Vasilyev -- http://kmansoft.wordpress.com

--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

Reply via email to