lilott8
lilott8

Reputation: 1116

ExpandableListView listview repeats views

I have an expandable list view where users can click a button to "save" a record. However, the listviews of my expandable listview seem to populate properly (the titles are different). But when a user "saves" element 1 it also saves elements 4,7,10,...n+3 (I know this because the view is set to invisible once it's saved). If you look below, I think I am recycling elements properly using the setTag() method in my getChildView() method.

I put some logging in my getChildView() for testing whether or not the view is cached is or drawn for the first time. The first two views are drawn and the rest are cached.

So my problem, as stated before is that when someone interacts with an element on the expandablelistview other elements are changed accordingly. record 1 has some data selected, which means record 4 and 7 is also selected. (and actually the elements of the subsequent elements of other groups in the elv

Here is my adapter:

public class SurveyListAdapter extends BaseExpandableListAdapter {
    private final SparseArray<Group> groups;
    public LayoutInflater inflater;
    private Context appContext;
    public String TAG = "SurveyListAdapter";
    private static SparseArray<SparseArray<Survey>> results = new SparseArray<SparseArray<Survey>>();
    //private static SparseArray<ArrayList<Boolean>> rowSubmitted = new SparseArray<ArrayList<Boolean>>();

    public SurveyListAdapter(Context context, SparseArray<Group> groups) {
        this.appContext = context;
        this.groups = groups;
        for(int i = 0;i<groups.size();i++) {
            Log.d(TAG, "Creating group: " + i);
            results.put(i, new SparseArray<Survey>());
        }
        //inflater = context.getLayoutInflater();
        this.inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE );
    }

    @Override
    public Survey getChild(int groupPosition, int childPosition) {
        //Log.d("getChild", "Group: " + groupPosition + "\tChild: " + childPosition);
        return this.groups.get(groupPosition).children.get(childPosition);
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        //return Long.parseLong(this.groups.get(groupPosition).children.get(childPosition));
        return childPosition;
    }

    public Survey getIdOfChild(int groupPosition, int childPosition) {
        return this.groups.get(groupPosition).children.get(childPosition);
    }

    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        View row = convertView;
        SurveyViewHolder svh;
        Survey child = getChild(groupPosition, childPosition);

        if (row == null) {
            row = inflater.inflate(R.layout.list_view_survey_row, parent, false);
            svh = new SurveyViewHolder();
            svh.title = (TextView) row.findViewById(R.id.tvSurveyTitle);
            svh.rg = (RadioGroup) row.findViewById(R.id.radioShared);
            svh.interest = (CheckBox) row.findViewById(R.id.checkBoxInterest);
            svh.privacy = (CheckBox) row.findViewById(R.id.checkBoxPrivacy);
            svh.rating = (RatingBar) row.findViewById(R.id.ratingBar);
            svh.submit = (Button) row.findViewById(R.id.btnSubmitRow);
            row.setTag(svh);
            Log.d(TAG, "Built from scratch");
        } else {
            Log.d(TAG, "Cached");
            svh = (SurveyViewHolder) row.getTag();
        }

        svh.title.setText(child.getTitle());
        svh.children = child.getTitle();

        svh.submit.setOnClickListener(new CustomOnClickListener(row, svh, groupPosition, childPosition));
        //this.registerClickListeners(groupPosition, childPosition, convertView);
        return row;
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        return groups.get(groupPosition).children.size();
    }

    @Override
    public Object getGroup(int groupPosition) {
        return groups.get(groupPosition);
    }

    @Override
    public int getGroupCount() {
        return groups.size();
    }

    @Override
    public void onGroupCollapsed(int groupPosition) {
        super.onGroupCollapsed(groupPosition);
    }

    @Override
    public void onGroupExpanded(int groupPosition) {
        super.onGroupExpanded(groupPosition);
    }

    @Override
    public long getGroupId(int groupPosition) {
        return groupPosition;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.xplist_view_survey_group, null);
        }
        Group group = (Group) getGroup(groupPosition);
        ((TextView) convertView).setText(group.string);
        //((CheckedTextView) convertView).setChecked(isExpanded);
        return convertView;
    }

    @Override
    public boolean hasStableIds() {
        return false;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return false;
    }

    public SparseArray<SparseArray<Survey>> getResults() {
        return results;
    }

    public void emptyResults() {
        for(int i=0; i<results.size();i++) {
            for(int j=0;j<results.get(i).size();j++) {
                results.get(i).remove(j);
            }
        }
    }

    public class SurveyViewHolder {
        public TextView title;
        public RadioGroup rg;
        public RatingBar rating;
        public CheckBox interest;
        public CheckBox privacy;
        public Button submit;
        public String children;
    }

    public class CustomOnClickListener implements View.OnClickListener {
        private View row;
        private SurveyViewHolder svh;
        private int group;
        private int child;

        public CustomOnClickListener(View r, SurveyViewHolder s, int g, int c) {
            this.row = r;
            this.svh = s;
            this.group = g;
            this.child = c;
        }

        @Override
        public void onClick(View v) {
            boolean addIt = false;
            try{
                if(results.get(this.group).get(this.child, null) == null) {
                    addIt = true;
                }
            } catch(NullPointerException e) {
                Log.d(TAG, "NPE");
                addIt = true;
            }

            if (addIt) {
                if (svh.rg.getCheckedRadioButtonId() > 0 && svh.rating.getRating() > 0) {
                    Boolean[] reasons = new Boolean[]{false, false, false};

                    // Hide the view
                    this.row.setVisibility(View.INVISIBLE);
                    // Start saving the record
                    Survey s = new Survey(svh.title.getText().toString());
                    s.setRating(svh.rating.getRating());
                    if (svh.privacy.isChecked()) {
                        reasons[0] = true;
                    } else if (svh.interest.isChecked()) {
                        reasons[1] = true;
                    }
                    s.setReason(reasons);
                    results.get(this.group).put(this.child, s);
                    Toast.makeText(appContext, "Record Saved", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(appContext, "You must give a rating and shared status", Toast.LENGTH_SHORT).show();
                }
            } else {
                Log.d(TAG, "Record already saved");
                this.row.setVisibility(View.INVISIBLE);
            }
        }
    }
}

Thank you for any help, I'm really struggling with this problem!

Upvotes: 2

Views: 1041

Answers (1)

olegr
olegr

Reputation: 2019

You set visibility to row in CustomOnClickListener and then reuse this invisible View for new items.

Suppose you pressed Save on second item. It is invisible now. Then if you scroll the second item's view would be reused for new item. Let say that it would be the item 5. Of course you see that 5'th item is hidden, because it is the same View as it was for second item.

Try to update visibility of row inside getChildView() in the same place where you update titles.

Upvotes: 2

Related Questions