lundi 9 mai 2016

Multi-level ExpandableListView with CheckBoxes in Android

I'm trying to implement a 3-level ExpandableListView in Android.

It looks something like this:

  • Level 1
    • Level 2
    • Level 2
      • Level 3
    • Level 2
  • Level 1
    • Level 2
    • Level 2

Level 2 and Level 3 are supposed to have CheckBoxes. And when CheckBox in Level 2 is selected, all his childrens in Level 3 are selected as well.

I've done 2 adapters - both extends BaseExpandableListAdapter. So in the end I get 2 inserted ExpandableLists - one for Level 1 - Level 2, and the other for Level 2 - Level 3.

Also I have 2 separate layouts - one for Level 1 and one for Levels 2-3 (since they are the same). It`s just a TextView with id inside RelativeView.

The questions:

  • When I'm changing TextView to CheckBoxe and setting the text to them, I cannot expand my list to the third level. I don't understand why it's happening and what to do with it, can anybody help me?

  • How can I hide indicators (those arrow showing expanded/collapsed state) from Level 2 items, which have no childrens?

  • I don't get why my ExpandableListView doesn't want to fit all the screen vertically, it consumes only 1/4 of it. I've tried to change some params in CustomExpandableListView, but it not worked.

Here some screenshots: Screenshot 1 Screenshot 2

As you can see, when I expand Asia list, the Europe list hides itself.

Here`s the code for Level 1:

public class RegionsAdapter extends BaseExpandableListAdapter {

private List<Object> objects;
private Activity activity;
private LayoutInflater inflater;

public RegionsAdapter(Activity activity, List<Object> objects) {
    this.objects = objects;
    this.activity = activity;
    this.inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public Object getChild(int groupPosition, int childPosition) {
    return objects.get(groupPosition).getObjects().get(childPosition);
}

@Override
public long getChildId(int groupPosition, int childPosition) {
    return childPosition;
}

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

    Object object = (Object) getChild(groupPosition, childPosition);
    CustomExpandableListView subObjects = (CustomExpandableListView) convertView;

    if (convertView == null) {
        subObjects = new CustomExpandableListView(activity);
    }
    CountriesAdapter adapter = new CountriesAdapter(activity, object);
    subObjects.setAdapter(adapter);

    return subObjects;
}

@Override
public int getChildrenCount(int groupPosition) {
    return objects.get(groupPosition).getObjects().size();
}

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

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

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

@Override
public View getGroupView(int groupPosition, boolean isExpanded,
                         View convertView, ViewGroup parent) {

    Object object = (Object) getGroup(groupPosition);
    if (convertView == null) {
        convertView = inflater.inflate(R.layout.layout_region_item, null);
    }

    TextView name = (TextView) convertView.findViewById(R.id.name);
    name.setText(object.getName());

    return convertView;
}

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

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

And code for Level 2-3:

public class CountriesAdapter extends BaseExpandableListAdapter {

private Object object;
private LayoutInflater inflater;
private Activity activity;

public CountriesAdapter(Activity activity, Object object) {
    this.activity = activity;
    this.object = object;
    this.inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public Object getChild(int groupPosition, int childPosition) {
    return object.getObjects().get(childPosition);
}

@Override
public long getChildId(int groupPosition, int childPosition) {
    return childPosition;
}

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

    Object object = (Object) getChild(0, childPosition);
    if (convertView == null) {
        convertView = inflater.inflate(R.layout.layout_country_item, null);

        Resources r = activity.getResources();
        float px40 = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 40, r.getDisplayMetrics());
        convertView.setPadding(
                convertView.getPaddingLeft() + (int) px40,
                convertView.getPaddingTop(),
                convertView.getPaddingRight(),
                convertView.getPaddingBottom());
    }

    TextView name = (TextView) convertView.findViewById(R.id.name);
    name.setText(object.getName());

    return convertView;
}

@Override
public int getChildrenCount(int groupPosition) {

    if (object.getObjects() == null) {
        return 0;
    }
    return object.getObjects().size();
}

@Override
public Object getGroup(int groupPosition) {
    return object;
}

@Override
public int getGroupCount() {
    return 1;
}

@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.layout_country_item, null);
        Resources r = activity.getResources();
        float px20 = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, r.getDisplayMetrics());
        convertView.setPadding(
                convertView.getPaddingLeft() + (int) px20,
                convertView.getPaddingTop(),
                convertView.getPaddingRight(),
                convertView.getPaddingBottom());
    }

    TextView name = (TextView) convertView.findViewById(R.id.name);
    name.setText(object.getName());

    return convertView;
}

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

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

Also I have some custom ExpandableListView:

public class CustomExpandableListView extends ExpandableListView {

public CustomExpandableListView(Context context) {
    super(context);
}

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    widthMeasureSpec = MeasureSpec.makeMeasureSpec(960, MeasureSpec.AT_MOST);
    heightMeasureSpec = MeasureSpec.makeMeasureSpec(600, MeasureSpec.AT_MOST);
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}

And my MainActivity code:

public class MainActivity extends AppCompatActivity {

public static CustomExpandableListView list;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    List<Item> objectsLvl1 = new ArrayList<Item>();

    List<Item> objectsAsia = new ArrayList<Item>();
    List<Item> objectsEurope = new ArrayList<Item>();

    List<Item> objectsChina = new ArrayList<Item>();

    List<Item> objectsGermany = new ArrayList<Item>();

    objectsLvl1.add(new Item("Asia", objectsAsia));
    objectsLvl1.add(new Item("Europe", objectsEurope));

    objectsAsia.add(new Item("China", objectsChina));
    objectsAsia.add(new Item("Japan"));

    objectsChina.add(new Item("Central", null));
    objectsChina.add(new Item("North", null));
    objectsChina.add(new Item("South", null));


    RelativeLayout parent = (RelativeLayout) findViewById(R.id.parent);

    list = new CustomExpandableListView(this);
    RegionsAdapter regionsAdapter = new RegionsAdapter(this, objectsLvl1);
    list.setAdapter(regionsAdapter);

    if (parent != null) {
        parent.addView(list);
    }
}
}




Aucun commentaire:

Enregistrer un commentaire