since m5 there is an Expandable List built in:
- android.widget.ExpandableListView is a new widget that provides a two-level tree-type widget. The top-level items are groups and are each expandable/collapsible to reveal the group's children. It shows indicators (by default) to the left of each item to show the current state of the item. The indicators along with the position they should be drawn are settable.
- The android.widget.ExpandableListAdapter provides data to this widget. It is similar to a regular Adapter, but has two sets of methods: one for groups and one for children.
- android.widget.SimpleCursorTreeAdapter transforms Cursors to data to be used by the ExpandableListView. Do note that these Cursors must be managed by the developer (in most cases, using android.app.Activity.managedQuery()), however the adapter may choose to deactivate a Cursor prior to the Activity deactivating it.
- android.widget.SimpleExpandableListAdapter transforms sets of data to be used by the ExpandableListView.
- There is an example in the API Demos > Views > Lists > Expandable > 1, 2, 3.
- Internally, this widget inherits from android.widget.ListView and has a connector to translate between "flat list" positions to group + child positions. Some methods will be available from ListView that return the "flat list" position, so developers should probably be aware of this. Worst case, there are methods exposed (getExpandableListPosition and getFlatListPosition) to convert between the two.
- The expandable list position is usually represented as a "packed position" containing the type of position (either child, group, or null), and a group position (for both group and children), and a child position (for children). Methods starting with getPackedPosition... help with unpacking.