Gratzi
Gratzi

Reputation: 4693

ExpandableListView - hide indicator for groups with no children

In an ExpandableListView, is there a way to hide the group indicator for groups with no children?

Upvotes: 117

Views: 98522

Answers (13)

ggaribotto
ggaribotto

Reputation: 1

The answers posted around here will make your group indicator gone even when a group has children.

To solve this, override the group indicator.

First, set your group indicator as null:

    ExpandableListView.setGroupIndicator(null);

Then, go to your xml that contains the header, and add an ImageView with your drawable.

After that, go to your ExpandableListAdapter.java, and in the "getGroupView" section, do the following:

public View getGroupView(int groupPosition, boolean isExpanded,
                         View convertView, ViewGroup parent) {
    String headerTitle = (String) getGroup(groupPosition);
    if (convertView == null) {
        LayoutInflater infalInflater = (LayoutInflater) this._context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = infalInflater.inflate(R.layout.list_group, null);
    }

    TextView lblListHeader = convertView
            .findViewById(R.id.lblListHeader); // this is your header

    ImageView groupIndicator = convertView.findViewById(R.id.group_indicator); // this is the ImageView included in your xml to override the indicator

    if (getChildrenCount(groupPosition) == 0) {
        convertView.setVisibility(View.GONE);
        lblListHeader.setVisibility(View.GONE);
        convertView.setPadding(0,0,0,0); //try not to include padding on your xml, and instead define the padding here.

    } else {
        convertView.setVisibility(View.VISIBLE);
        convertView.setPadding(8,8,8,0);
        lblListHeader.setVisibility(View.VISIBLE);
        lblListHeader.setTypeface(font);
        lblListHeader.setText(headerTitle);
        if (isExpanded) { //this is the part where we define our group indicator based on the expanded status of the adapter
            groupIndicator.setImageResource(R.drawable.group_indicator_expanded);
        } else {
            groupIndicator.setImageResource(R.drawable.group_indicator_empty);
        }
    }

    return convertView;
}

Upvotes: 0

Saurabh Agarwal
Saurabh Agarwal

Reputation: 139

In XML

android:groupIndicator="@null"

In ExpandableListAdapter -- > getGroupView copy following code

if (this.mListDataChild.get(this.mListDataHeader.get(groupPosition)).size() > 0){
      if (isExpanded) {
          arrowicon.setImageResource(R.drawable.group_up);
      } else {
          arrowicon.setImageResource(R.drawable.group_down);
      }
}

Upvotes: 13

keyboard_kracker22
keyboard_kracker22

Reputation: 71

Just wanted to improve on Mihir Trivedi's answer. You can place this within getGroupView() that's inside MyExpandableListAdapter class

    View ind = convertView.findViewById(R.id.group_indicator);
    View ind2 = convertView.findViewById(R.id.group_indicator2);
    if (ind != null)
    {
        ImageView indicator = (ImageView) ind;
        if (getChildrenCount(groupPosition) == 0)
        {
            indicator.setVisibility(View.INVISIBLE);
        }
        else
        {
            indicator.setVisibility(View.VISIBLE);
            int stateSetIndex = (isExpanded ? 1 : 0);

            /*toggles down button to change upwards when list has expanded*/
            if(stateSetIndex == 1){
                ind.setVisibility(View.INVISIBLE);
                ind2.setVisibility(View.VISIBLE);
                Drawable drawable = indicator.getDrawable();
                drawable.setState(GROUP_STATE_SETS[stateSetIndex]);
            }
            else if(stateSetIndex == 0){
                ind.setVisibility(View.VISIBLE);
                ind2.setVisibility(View.INVISIBLE);
                Drawable drawable = indicator.getDrawable();
                drawable.setState(GROUP_STATE_SETS[stateSetIndex]);
            }
        }
    }

...and as for the layout view, this is how my group_items.xml appears to be

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
    android:id="@+id/group_heading"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:paddingLeft="20dp"
    android:paddingTop="16dp"
    android:paddingBottom="16dp"
    android:textSize="15sp"
    android:textStyle="bold"/>

<ImageView
    android:id="@+id/group_indicator"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@android:drawable/arrow_down_float"
    android:layout_alignParentRight="true"
    android:paddingRight="20dp"
    android:paddingTop="20dp"/>

<ImageView
    android:id="@+id/group_indicator2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@android:drawable/arrow_up_float"
    android:layout_alignParentRight="true"
    android:visibility="gone"
    android:paddingRight="20dp"
    android:paddingTop="20dp"/>

Hope that helps...remember to leave an upvote

Upvotes: 2

Amt87
Amt87

Reputation: 5607

Try this >>>

for all items

 getExpandableListView().setGroupIndicator(null);

In xml

android:groupIndicator="@null"

Upvotes: 118

Vadym Vikulin
Vadym Vikulin

Reputation: 56

convertView.setVisibility(View.GONE) should do the trick.

@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
    DistanceHolder holder;
    if (convertView == null) {
        convertView = LayoutInflater.from(context).inflate(R.layout.list_search_distance_header, parent, false);
        if (getChildrenCount(groupPosition)==0) {
            convertView.setVisibility(View.GONE);
        }

Upvotes: -3

Rajat Gupta
Rajat Gupta

Reputation: 127

Have you tried to change ExpandableListView's attribute android:groupIndicator="@null"?

Upvotes: 1

Sarwar Erfan
Sarwar Erfan

Reputation: 18068

The android:groupIndicator property takes a state enabled drawable. That is, you can set different image for different states.

When the group has no children, the corresponding state is 'state_empty'

See these reference links:

this and this

For state_empty, you can set a different image which is not confusing, or, simply use transparent color to display nothing...

Add this item in your stateful drawable along with others....

<item android:state_empty="true" android:drawable="@android:color/transparent"/>

So, your statelist can be like this:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_empty="true" android:drawable="@android:color/transparent"/>
    <item android:state_expanded="true" android:drawable="@drawable/my_icon_max" />
    <item android:drawable="@drawable/my_icon_min" />
</selector>

In case you are using an ExpandableListActivity, you can set the groupindicator in onCreate as follows:

getExpandableListView().setGroupIndicator(getResources().getDrawable(R.drawable.my_group_statelist));

I have tested this to be working.

Upvotes: 88

Tran Hieu
Tran Hieu

Reputation: 5374

Simply, you create a new xml layout with height=0 for the hidden group header. For example, it's 'group_list_item_empty.xml'

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"              
              android:layout_width="match_parent"
              android:layout_height="0dp">
</RelativeLayout>

Then your normal group header layout is 'your_group_list_item_file.xml'

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="48dp"
              android:orientation="horizontal">
    ...your xml layout define...
</LinearLayout>

Finally, you just update the getGroupView method in your Adapter Class:

public class MyExpandableListAdapter extends BaseExpandableListAdapter{   

    //Your code here ...

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup viewGroup) {
        if (Your condition to hide the group header){
            if (convertView == null || convertView instanceof LinearLayout) {
                LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
                convertView = mInflater.inflate(R.layout.group_list_item_empty, null);
            }           
            return convertView;
        }else{      
            if (convertView == null || convertView instanceof RelativeLayout) {
                LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
                convertView = mInflater.inflate(R.layout.your_group_list_item_file, null);              
            }   
            //Your code here ...
            return convertView;
        }
    }
}

IMPORTANT: The root tag of the layout files (hidden and normal) must be different (as above example, LinearLayout and RelativeLayout )

Upvotes: 0

  Evgeny Karavashkin
Evgeny Karavashkin

Reputation: 176

suggest you my solution:

1)Clear default groupIndicator :

<ExpandableListView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"       
    android:layout_width="wrap_content"
    android:layout_height="240dp"        
    android:layout_gravity="start"
    android:background="#cccc"  
    android:groupIndicator="@android:color/transparent"     
    android:choiceMode="singleChoice"
    android:divider="@android:color/transparent"        
    android:dividerHeight="0dp"  
     />

2) in ExpandableAdapter:

@Override
public View getGroupView(int groupPosition, boolean isExpanded,
        View convertView, ViewGroup parent) {
    if (convertView == null) {
        convertView = new TextView(context);
    }
    ((TextView) convertView).setText(groupItem.get(groupPosition));     
    ((TextView) convertView).setHeight(groupHeight);
    ((TextView) convertView).setTextSize(groupTextSize);

    //create groupIndicator using TextView drawable
    if (getChildrenCount(groupPosition)>0) {
        Drawable zzz ;
        if (isExpanded) {
            zzz = context.getResources().getDrawable(R.drawable.arrowup);
        } else {
            zzz = context.getResources().getDrawable(R.drawable.arrowdown);
        }                               
        zzz.setBounds(0, 0, groupHeight, groupHeight);
        ((TextView) convertView).setCompoundDrawables(null, null,zzz, null);
    }       
    convertView.setTag(groupItem.get(groupPosition));       

    return convertView;
}

Upvotes: 4

Mihir Trivedi
Mihir Trivedi

Reputation: 1505

In your code just use the custom xml for group list and in that put the ImageView for GroupIndicator.

And Add below arrays in your ExpandableListAdapter

private static final int[] EMPTY_STATE_SET = {};
private static final int[] GROUP_EXPANDED_STATE_SET = { android.R.attr.state_expanded };
private static final int[][] GROUP_STATE_SETS = { EMPTY_STATE_SET, // 0
GROUP_EXPANDED_STATE_SET // 1
};

also in ExpandableListAdapter's method add same things as below

public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) 
{ 
    if (convertView == null) 
    {
        LayoutInflater infalInflater = (LayoutInflater) this._context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = infalInflater.inflate(R.layout.row_group_list, null);
    }

    //Image view which you put in row_group_list.xml
    View ind = convertView.findViewById(R.id.iv_navigation);
    if (ind != null)
    {
        ImageView indicator = (ImageView) ind;
        if (getChildrenCount(groupPosition) == 0) 
        {
            indicator.setVisibility(View.INVISIBLE);
        } 
        else 
        {
            indicator.setVisibility(View.VISIBLE);
            int stateSetIndex = (isExpanded ? 1 : 0);
            Drawable drawable = indicator.getDrawable();
            drawable.setState(GROUP_STATE_SETS[stateSetIndex]);
        }
    }

    return convertView;
}

Reference: http://mylifewithandroid.blogspot.in/2011/06/hiding-group-indicator-for-empty-groups.html

Upvotes: 12

jenzz
jenzz

Reputation: 7269

Based on StrayPointer's answer and the code from the blog, you can simplify the code even more:

In your xml add the folowing to ExpandableListView:

android:groupIndicator="@android:color/transparent"

Then in the Adapter you do the following:

@Override
protected void bindGroupView(View view, Context paramContext, Cursor cursor, boolean paramBoolean){
    **...**

    if ( getChildrenCount( groupPosition ) == 0 ) {
       indicator.setVisibility( View.INVISIBLE );
    } else {
       indicator.setVisibility( View.VISIBLE );
       indicator.setImageResource( isExpanded ? R.drawable.list_group_expanded : R.drawable.list_group_closed );
    }
}

By using the setImageResource method you get it all done with a one-liner. You do not need the three Integer arrays in your adapter. You also do not need an XML selector for state expanded and collapsed. All is done via Java.

Plus, this approach also displays the correct indicator when a group is expanded by default what does not work with the code from the blog.

Upvotes: 45

Asad Rao
Asad Rao

Reputation: 3250

Use this it is perfectly working for me.

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

<item android:drawable="@drawable/group_indicator_expanded" android:state_empty="false" android:state_expanded="true"/>
<item android:drawable="@drawable/group_indicator" android:state_empty="true"/>
<item android:drawable="@drawable/group_indicator"/>

</selector>

Upvotes: 1

StrayPointer
StrayPointer

Reputation: 1304

As mentioned in a different answer, since Android treats an un-expanded list group as empty, the icon is not drawn even if the group has children.

This link solved the problem for me: http://mylifewithandroid.blogspot.com/2011/06/hiding-group-indicator-for-empty-groups.html

Basically you have to set the default drawable as transparent, move the drawable into your group view as an ImageView and toggle the image in your adapter.

Upvotes: 26

Related Questions