When we have a ListView expandable inside ScrollView, we must make this in our layout, always expandable listview must be the last view in our layout:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_expandable_scroll_view" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true"> <LinearLayout android:id="@+id/LinearLayout1" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin"> <!-- your code ---> <ExpandableListView android:id="@+id/activity_expandable_list_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/white"/> </LinearLayout> </ScrollView>
In your onCreate
mListView = (ExpandableListView) findViewById(R.id.activity_expandable_list_view); MyExpandableListAdapter adapter = new MyExpandableListAdapter(this, mGroups); mListView.setAdapter(adapter); mListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() { @Override public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) { setListViewHeight(parent, groupPosition); return false; } });
You need this function:
private void setListViewHeight(ExpandableListView listView, int group) { ExpandableListAdapter listAdapter = (ExpandableListAdapter) listView.getExpandableListAdapter(); int totalHeight = 0; int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(), View.MeasureSpec.EXACTLY); for (int i = 0; i < listAdapter.getGroupCount(); i++) { View groupItem = listAdapter.getGroupView(i, false, null, listView); groupItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED); totalHeight += groupItem.getMeasuredHeight(); if (((listView.isGroupExpanded(i)) && (i != group)) || ((!listView.isGroupExpanded(i)) && (i == group))) { for (int j = 0; j < listAdapter.getChildrenCount(i); j++) { View listItem = listAdapter.getChildView(i, j, false, null, listView); listItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED); totalHeight += listItem.getMeasuredHeight(); } } } ViewGroup.LayoutParams params = listView.getLayoutParams(); int height = totalHeight + (listView.getDividerHeight() * (listAdapter.getGroupCount() - 1)); if (height < 10) height = 200; params.height = height; listView.setLayoutParams(params); listView.requestLayout(); }
This solution worked , thanks !!!
Well done 🙂
it worked for me thanks saved my day. 🙂
Hello
it is working for me but i tried to understand the content of the function setListViewHeight but i didn’t understand it
please if u have time to explain what u are doing in it i will be very happy
thank u in advance
Hi!!! of course!!!
I hope that my explanation will help you
The first step, we create variable height and width.
for each group we add group’s height.
if group is expandable, for each item we add item’s height.
We use params
LayoutParams are used by views to tell their parents how they want to be laid out. See ViewGroup Layout Attributes for a list of all child view attributes that this class supports.
Then we add divider height * number of group and we get total height in List.
getDividerHeight ()
Returns the height of the divider that will be drawn between each item in the list.
Now we check the minimum.
we add height to params
the last line we use
requestLayout()
Call this when something has changed which has invalidated the layout of this view.
Try to Make it in c# xamarin it will be great help for me.
Hi,
Thanks for the code. It works great once the group item is clicked but it only shows one group item initially. Any help is appreciated!
It works fine for me .
But I have a problem in my case I don’t want to re-create activity on orientation change so I restrict it through manifest file so resolution specification I calculated in portrait mode reflected in landscape also , that’s why when I rotate my device it shows extra space in after last child .
Please help…
Thanks in advance 🙂
A lot of thanks. Its working perfectly. Really nice .
Thanks again.
If you want to set height of exp. listview, when activity will start, you can use this function:
setListViewHeightForGroups(your_expList_AfterAcceptingAdapter);
public void setListViewHeightForGroups(ExpandableListView listView){
ExpandableListAdapter listAdapter = (ExpandableListAdapter) listView.getExpandableListAdapter();
int totalHeight = 0;
int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),
View.MeasureSpec.EXACTLY);
for (int i = 0; i < listAdapter.getGroupCount(); i++) {
View groupItem = listAdapter.getGroupView(i, false, null, listView);
groupItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
totalHeight += groupItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
int height = totalHeight
+ (listView.getDividerHeight() * (listAdapter.getGroupCount() – 1));
if (height < 10)
height = 200;
params.height = height;
listView.setLayoutParams(params);
listView.requestLayout();
}
This is not worked for me. please help me
This code should work. Which is your error?
NO error. calculating wrong height. For E.g If Actual height is 2378 but it’s 3500
But i click on expand it is working fine.
Worked!! Great work.
Is this condition right?
if (((listView.isGroupExpanded(i)) && (i != group))
|| ((!listView.isGroupExpanded(i)) && (i == group))) {
Seems like its never satisfies the condition.
oh, i got it, i was using in groupexpand and not on groupclick. i changed the condition, so its working on groupexpand
Thank you so much.
Thank you for this nice solution !
I just have an issue, I set android:dividerHeight=”5dp” in my ExpandableListView but when doing that I only see the first item.
What did I miss ?
Thank you
Maybe because Android can´t calculate height when you set dividerHeight. Android is not perfect.
Thanks! It works (almost).
However , it only works after you click on a group item.
What about when you just open the layout and haven’t opened any group item?
Hi
In your adapter you have to call a expandGroup… https://developer.android.com/reference/android/widget/ExpandableListView.html#expandGroup(int)
Gracias !!!. Thank you so much.
Great! Thnx a lot!!!!!
It worked like a cake.. thanks for the solution !
Great! work good.:-)
it is not working if i give an 500 child value is hide some group values
for (int j = 0; j < 5; j++) {
Group group = new Group("Test " + j);
for (int i = 0; i < 500; i++) {
group.children.add("Sub Item" + i);
}
mGroups.append(j, group);
}
i give this much of count it hide some values
is this correct??please help me….
private void setListViewHeight(ExpandableListView listView,
int group) {
ExpandableListAdapter listAdapter = (ExpandableListAdapter) listView.getExpandableListAdapter();
int totalHeight = 0;
int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),
View.MeasureSpec.AT_MOST);
for (int i = 0; i < listAdapter.getGroupCount(); i++) {
View groupItem = listAdapter.getGroupView(i, false, null, listView);
groupItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
totalHeight += groupItem.getMeasuredHeight();
if (((listView.isGroupExpanded(i)) && (i != group))
|| ((!listView.isGroupExpanded(i)) && (i == group))) {
for (int j = 0; j < listAdapter.getChildrenCount(i); j++) {
View listItem = listAdapter.getChildView(i, j, false, null,
listView);
listItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
totalHeight += listItem.getMeasuredHeight();
}
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
int height = totalHeight
+ (listView.getDividerHeight() * (listAdapter.getGroupCount() – 1));
if (height < 10)
height = 200;
params.height = height;
listView.setLayoutParams(params);
listView.requestLayout();
}
}
I have put explistview inside Linearlayout. when I click on the last group, it don’t scroll to end of last group. when I remove Linearlayout, it’s ok. how can I fix it ?? This is my code:
Where is your code?
Thanks for your solution…
My problem is solved. Ohhhh thanks a loooootttt
How can I use this, When the first group is expanded when activity started. In Marshmallow OS I got long white space
Thanks a lot , its working fine .
But if Expandable view having a DividerHeight then below line is required inside inner for loop. Neither it was creating spacing problem and hiding the Group.
totalHeight = totalHeight+ (listView.getDividerHeight()*listAdapter.getChildrenCount(i)-1);
/******************************************************************/
private void setListViewHeight(ExpandableListView listView,
int group) {
ExpandableListAdapter listAdapter = listView.getExpandableListAdapter();
int totalHeight = 0;
int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),
View.MeasureSpec.EXACTLY);
for (int i = 0; i < listAdapter.getGroupCount(); i++) {
View groupItem = listAdapter.getGroupView(i, false, null, listView);
groupItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
totalHeight += groupItem.getMeasuredHeight();
if (((listView.isGroupExpanded(i)) && (i != group))
|| ((!listView.isGroupExpanded(i)) && (i == group))) {
for (int j = 0; j < listAdapter.getChildrenCount(i); j++) {
View listItem = listAdapter.getChildView(i, j, false, null,
listView);
listItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
totalHeight += listItem.getMeasuredHeight();
}
totalHeight = totalHeight+ (listView.getDividerHeight()*listAdapter.getChildrenCount(i)-1);
}
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
int height = totalHeight
+ (listView.getDividerHeight() * (listAdapter.getGroupCount() – 1));
if (height < 10)
height = 200;
params.height = height;
listView.setLayoutParams(params);
listView.requestLayout();
}
This solution helped me. Thank You BOSS
It worked for me. The problem is the initial view only shows the first group (or first item of the list group) and after clicking that is when the rest of the groups be only view-able.
It worked for me. But facing one problem , the problem is the initial view only shows the first group (or first item of the list group) and after clicking that is when the rest of the groups be visible.
I have to click on first group. then ‘setOnGroupClickListener’ invokes and set dynamic height.
I try to call ‘setListViewHeight’ method, out side of ‘ ‘setOnGroupClickListener’ block. like below
setListViewHeight(expListView, groupPosition);
but then problem is what will be what will be groupPosition value? then I placed
inside for loop,
for(int i = 1; i< expandableList.size(); i++){
setListViewHeight(expandableListView,i);
}
But it show unwanted extra space below expandable listview. it is actually measuring extra height.
what else I can do?
did u solved this issue…please help me also i m facing the same issue.
You sir, I owe you a beer.
Awesome..Thanks man
its not working for me.can you please help me out
Hi Cabezas,
I am using above code, working absolutely fine. But, when i try to expand list item and expand on other item. The list view height is varying on the basis of previous expanded item.i.e unnecessary height is appending at the bottom of the list view.
Can you help to fix this issue please?
Thanks in Advance
Sri
I am Great Thankful to you, for such a nice and informative tutorial, This tutorial Saved my life, i was facing the same problem for three days
Its not working my side
You are legend! IT WORKS!
Excellent solution. this saved my time.