ExpandableListView group indicator bounds nonsense

Digging deeper into ExpandableListView I came across another weird API design issue. This one is about ExpandableListView group indicator images.

These images are displayed on the left side of a group row in the list. As the name suggests they indicate if the group is expanded or collapsed. Obviously there can be two different images here and Android supports it. You can write an XML drawable selector (setGroupIndicator (Drawable groupIndicator)) with two states: state_empty for collapsed and state_expanded for an expanded group.

Well, what is also obvious to me is the fact that two images can have two different sizes, right? Apparently it is not so obvious to people who designed this part of Android API. You can have two different images for two different group states, but… both images will be stretched to fit the size you set by ExpandableListView‘s setIndicatorBounds(int left, int right) method.

What options do you have? You can set indicator bounds (via setIndicatorBounds(int left, int right)) to match wider one of your two images and compensate for differences using this kind of selector:

<selector xmlns:android="http://schemas.android.com/apk/res/android" >

    <item android:state_empty="true">
        <layer-list>
        	<item
			    android:left="0dp"
			    android:right="20dp"
			    android:top="10dp"
			    android:bottom="10dp"
			    android:drawable="@drawable/collapsed_image">
 			</item>
 		</layer-list>
    </item>

    <item android:state_expanded="true">
        <layer-list>
        	<item
			    android:left="0dp"
			    android:right="0dp"
			    android:top="10dp"
			    android:bottom="10dp"
			    android:drawable="@drawable/expanded_image">
 			</item>
 		</layer-list>
    </item>

</selector>

In above example the expanded image is a wider one, so we compensate 20dp in android:right coordinate of the collapsed image. As you can see there are also some sample top and bottom margins for both images.

Second option is to convert your images to a 9-patches, carefully selecting stretchable and non-stretchable parts. As it deals with image editing by hand I consider this solution impractical.

You can also set your indicator to @null in selector items and put your indicator views inside XML row layouts. You will have to write a custom ExpandableListAdapter and display/hide indicator views after inflating these from your row layout in getGroupView implementation.

I haven’t tested it yet, but this looks like the best solution. Ditch this useless feature of group indicators and do it your way.

Leave a comment