ExpandableListView - hide indicator for groups with no children
Asked Answered
T

13

117

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

Tasker answered 10/11, 2010 at 13:45 Comment(1)
To clarify: Is there a way to hide the group indicator ONLY for groups with no children?Selfpreservation
D
118

Try this >>>

for all items

 getExpandableListView().setGroupIndicator(null);

In xml

android:groupIndicator="@null"
Doronicum answered 7/8, 2012 at 12:42 Comment(8)
I believe that will set the groupIndicator for all items and not just those without children.Morphology
Tested and don't works. This simple hide all indicators either has children or not.Daffy
myExpandableListView.setGroupIndicator(null); works for meCircuity
@Morphology is there any way to hide the indicator for groups without child??Xenocrates
@Xenocrates that's the topic of the questionMorphology
@Morphology But the above solution will remove the indicator from all the groups with or without childs.Do u have any valuable solution for this??Xenocrates
It hides all the indicators not the ones with no child.Lucerne
Yes @SamiraElhami, I have noticed this but unfortunately I thought that the question was talking about all indicators and I didn't see the "no children" constraint. So, I edited my answer by mentioning that it is for all.Doronicum
K
88

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.

Kwasi answered 30/12, 2010 at 12:18 Comment(4)
Not working: Tested in Android 4.0.2 (ICS). See other responses to this question on this page. It seems Android considers un-expanded group as empty. Just set the group indicator to transparent, then add a imageView to your group row and in getGroupView method of adapter, set it to the icon you want.Passim
This code do not work form me either (tested on Android 4.4).Unexpanded group is considered as empty (no children) so the icon is set to color/transparent.Begun
Thanks for code, but it looks like a joke: so complex code for such a simple task?Lientery
Hard to believe this answer received so many 'useful' and a bounty while it is documented that collapsed groups are considered empty for performance reasons!Roberge
T
45

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.

Trixie answered 10/7, 2012 at 15:29 Comment(5)
This is meant to be used in the getGroupView() method of your BaseExpandableListAdapter implementation. Have a look at this example implementation.Trixie
@Trixie What is the "indicator"?Philender
He use the ViewHolder pattern. indicator is the variable name of the view holder.Begun
indicator is an Imageview.The image you want to display based on the statesTimpani
indicator refers to the explist_indicator Imageview in the group_row xml: <?xml?> <LinearLayout android:orientation="horizontal" android:layout_height="wrap_content" android:layout_width="fill_parent"> <ImageView android:layout_height="20px" android:layout_width="20px" android:id="@+id/explist_indicator" android:src="@drawable/expander_group"/> <TextView android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/groupname" android:paddingLeft="30px" android:textStyle="bold" android:textSize="16px"/> </LinearLayout>Ila
G
26

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.

Grackle answered 26/8, 2011 at 15:38 Comment(0)
T
13

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);
      }
}
Taster answered 20/5, 2018 at 10:24 Comment(1)
How to use DEFAULT drawables? It says: Cannot resolve symbol 'group-up'Scintilla
F
12

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

Ferrante answered 20/3, 2014 at 9:47 Comment(0)
H
4

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;
}
Holoenzyme answered 3/10, 2014 at 12:23 Comment(1)
@stackoverflow.com/users/4090796/evgeny-karavashkin what is "arrowup" ?Scintilla
B
2

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

Bourguiba answered 28/2, 2017 at 20:35 Comment(0)
N
1

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>
Nomination answered 24/10, 2013 at 11:27 Comment(1)
Could you post your ExpandableListView code as well? This isn't working for me (the group_indicator appears for groups with and without children).Capriccio
P
1

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

Prothesis answered 12/6, 2015 at 15:25 Comment(0)
R
0

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 )

Rubber answered 16/10, 2014 at 15:3 Comment(0)
A
0

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;
}
Awestricken answered 28/1, 2021 at 17:5 Comment(0)
F
-3

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);
        }
Formulate answered 12/12, 2015 at 15:2 Comment(2)
This just removes all the items: List is empty --> me is sad :(Ignore
have you added counter check? if (getChildrenCount(groupPosition)==0) {Formulate

© 2022 - 2024 — McMap. All rights reserved.