1

I'm trying to realize a layout with an ExpendableListView. There are 4 Group Elements and for each Group 2 Children. The first Group Element does have 0 Children.

G
G
 C
 C
G
 C
 C
G
 C
 C

Every Group Element has 2 TextViews, 1 ImageView and 1 Switch. Every Child Element has 2 TextViews and 1 SeekBar.

The Adapter contains 2 Holder. One for the Groupviews and one for the Childviews.

On the Group Layer everything works as intented.

But on the Child Layer the different ChildViews are interdependend. For example setting the SeekBar of Group Element3/Child Element1 sets the SeekBar of Group Element1/Child Element0 too.

I do understand the problem has something to do with missing uniques of the views and view handling(optimizing) by Android.

Here is the getChildView method:

@Override
public View getChildView(int groupPosition, int childPosition,
    boolean isLastChild, View convertView, ViewGroup parent) {

final int tempgroupPos = groupPosition;
final int tempchildPos = childPosition;

ChildViewHolder cviewHolder = null; 

if (convertView == null) {  
    convertView = inflater.inflate(R.layout.interfaces_listrow_details_intervall, null);

    cviewHolder  = new ChildViewHolder();

    cviewHolder.tvb = (TextView) convertView.findViewById(R.id.interfaces_child_intervall_textbig);
    cviewHolder.tvs = (TextView) convertView.findViewById(R.id.interfaces_child_intervall_textexplanation);
    cviewHolder.sb = (SeekBar) convertView.findViewById(R.id.interfacesSeekBar);

    cviewHolder.sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            // TODO Auto-generated method stub      
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            // TODO Auto-generated method stub      
        }

        @Override
        public void onProgressChanged(SeekBar seekBar, int progress,
                boolean fromUser) {

            int getPosition = (Integer) seekBar.getTag();   

            clist.get(tempgroupPos).get(tempchildPos).setProgress(seekBar.getProgress());

            // do stuff

            notifyDataSetChanged();
        }
    });

    convertView.setTag(cviewHolder);

    convertView.setTag(R.id.interfaces_child_intervall_textbig, cviewHolder.tvb);
    convertView.setTag(R.id.interfaces_child_intervall_textexplanation, cviewHolder.tvs);
    convertView.setTag(R.id.interfacesSeekBar, cviewHolder.sb);

} else {
    cviewHolder = (ChildViewHolder) convertView.getTag();
}

cviewHolder.sb.setTag(groupPosition);
cviewHolder.sb.setProgress(clist.get(groupPosition).get(childPosition).getProgress());

cviewHolder.tvb.setText(clist.get(groupPosition).get(childPosition).getBigText());  
cviewHolder.tvs.setText(clist.get(groupPosition).get(childPosition).getSmallTextActivated());

return convertView;
}

If you need any other part of the code or other informations please ask.

I looked into these Question/Answers but they did not really help me personally.

Community
  • 1
  • 1
  • Are the views in the `ChildViewHolder` declared as static? Also, set the listener outside of the `if` clause, after you set the progress on the `SeekBar`. – user Jun 06 '14 at 15:47
  • Can you tell me what is clist? specifically this line clist.get(tempgroupPos).get(tempchildPos).setProgress(seekBar.getProgress()); – Madhur Ahuja Jun 06 '14 at 16:04
  • Wow, I am not used to such fast answers. Sry. @Luksprog The Views in the ChildViewHolder are declared as Static class with protected vars. I've set now the listener outside of the if clause. /// clist is a "private final List> clist;". It is suposed to hold the text and the progress values of the view elements. Here it contains 3 List objects with 2 Model objects itself. 1 Model holds the Strings and values of 1 ListView Element. – pizza_exclamationMark Jun 06 '14 at 20:53

2 Answers2

1

OK. Besides I am not really sure why this approach won't work I looked again on the posted links to Q/A. I've choosed this one

Android - Expandable ListView - using ViewHolder for optimization

and followed everything exactly. Now it works that way. I focused to much on my first choosen example. Thank you. My code is working now. Here is the code for others to refer.

ChildViewHolder:

// https://stackoverflow.com/questions/22583689/android-expandable-listview-using-viewholder-for-optimization
static class ChildViewHolder {
    private HashMap<Integer, View> storedViews = new HashMap<Integer, View>();


    public ChildViewHolder addView(View view)
    {
        int id = view.getId();
        storedViews.put(id, view);
        return this;
    }

    public View getView(int id)
    {
        return storedViews.get(id);
    }
}

getChildView Method:

@Override
public View getChildView(int groupPosition, int childPosition,
        boolean isLastChild, View convertView, ViewGroup parent) {

    final int tempgroupPos = groupPosition;
    final int tempchildPos = childPosition;

    View row = convertView;
    if (row == null)
    {
        row = inflater.inflate(R.layout.interfaces_listrow_details_intervall, parent, false);

        TextView tvb = (TextView) row.findViewById(R.id.interfaces_child_intervall_textbig);
        TextView tvs = (TextView) row.findViewById(R.id.interfaces_child_intervall_textexplanation);
        SeekBar sb = (SeekBar) row.findViewById(R.id.interfacesSeekBar);

        ChildViewHolder cholder = new ChildViewHolder();

        cholder.addView(tvb);
        cholder.addView(tvs);
        cholder.addView(sb);

        row.setTag(cholder);
    }

    ChildViewHolder cholder = (ChildViewHolder) row.getTag();
    TextView tvb = (TextView) cholder.getView(R.id.interfaces_child_intervall_textbig);
    TextView tvs = (TextView) cholder.getView(R.id.interfaces_child_intervall_textexplanation);
    SeekBar sb = (SeekBar) cholder.getView(R.id.interfacesSeekBar);

    sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            // TODO Auto-generated method stub
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            // TODO Auto-generated method stub  
        }

        @Override
        public void onProgressChanged(SeekBar seekBar, int progress,
                boolean fromUser) {

            Globals g = Globals.getInstance();
            clist.get(tempgroupPos-1).get(tempchildPos).setProgress(seekBar.getProgress());

            // do something
            notifyDataSetChanged();
        }
    });

    tvb.setText(clist.get(groupPosition-1).get(childPosition).getBigText());
    tvs.setText(clist.get(groupPosition-1).get(childPosition).getSmallTextActivated());
    sb.setProgress(clist.get(groupPosition-1).get(childPosition).getProgress());

    return row;
}
Pradip Shenolkar
  • 818
  • 1
  • 14
  • 34
-1

This tutorial is about Expandable List view in android which helps to display data in group. You can create multiple listview in your activity which can be expanded on click event. Main idea of Android Expandable listview is that it has groups and every group has some Child. Groups can be expanded and shirked by clicking on them.

Expandable List view is mainly used to display data in groups. The main difference between ordinary list view and list view is that this allows two levels: groups and children (groups are individually expanded). for more imformation checkout http://techlovejump.com/android-expandable-listview-tutorial/