An Expand/Collapse button in Android (to show/hide an optional view)

I need a UI element that will allow the user to expand/collapse (show/hide) a view that contains optional/advanced information.

I envision this as a text label (e.g. ‘advanced options’, ‘more/less’) plus an icon that toggles between open and close. I’ve got some icons that could serve the purpose, and the functionality of the element closely matches that of a ToggleButton, so I attempted to solve this problem with a styled ToggleButton.

This solution turned out to be super ugly (from the maintenance perspective). I’ll add it as an answer below.

I’m hoping someone could suggest a better solution, or point out how my solution could be simplified.

BTW, animating the expanding/collapsing of the view is addressed well in this SO Q/A.

Answer

Thankfully, I’ve found a much simpler way.

Instead of using a ToggleButton (which involved 11 resource files to style it) I’m just using a TextView with a CompoundDrawable, and then managing the state myself.

This way involves a little more code, but saves a huge mess of resource files. It also makes it easier to handle multiple themes, e.g. here I set the resource ID’s for the needed icons depending on the theme:

final MainActivity ma = (MainActivity) getActivity();
if  (ma.isDarkTheme()) {
    icon_expand = getResources().getIdentifier( "ic_action_expand","drawable", ma.getPackageName() );       
    icon_collapse = getResources().getIdentifier( "ic_action_collapse","drawable", ma.getPackageName() );       
} else {
    icon_expand = getResources().getIdentifier( "ic_action_expand_light","drawable", ma.getPackageName() );     
    icon_collapse = getResources().getIdentifier( "ic_action_collapse_light","drawable", ma.getPackageName() );     
}

I do this in my fragment’s onCreate. It is unfortunate that I have to resolve the icon ID’s at runtime, but that seems to be how it is done.

I have no idea why my icons are displayed at normal size in this case and at double size when I specified them as a layer of the background of the ToggleButton (which necessitating ScaledDrawable resources for all of my icons).

Here is my onClickListener (for the TextView):

protected OnClickListener expandCtrlListener = new OnClickListener() {
    public void onClick(View v) {
        assertTrue( v == expandCtrl );
        isExpanded = !isExpanded;
        advancedView.setVisibility( isExpanded ?  View.VISIBLE : View.GONE );
        expandCtrl.setCompoundDrawablesWithIntrinsicBounds( isExpanded ? icon_collapse : icon_expand, 0, 0, 0 );
    }
};

Note that none of this shows the animation of the expand/collapse. That is addressed in the article I mention at the end of the question.

Leave a Reply

Your email address will not be published. Required fields are marked *