Reputation: 55
I am using expandable list view to make 3 - level hierarchy, would like to know how to set internal list height and width. I knew we have onMeasure for this purpose but in my case it not allowing me to capture whole space of parent list view.
may be I am giving wrong value to it, here is the code which is I am using for setting height and width of child expandable list.
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
widthMeasureSpec = MeasureSpec.makeMeasureSpec(960,MeasureSpec.AT_MOST);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(800,MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
Currently it appearing as follow
<ParentGroup1 >
<ChildParentGroup>
<Child1>
<Child2>
<child3>
<ParentGroup2 >
and it should appear like below.
<ParentGroup1 >
<ChildParentGroup >
<Child1 >
<Child2 >
<child3 >
<ParentGroup2 >
Please advise/suggest for the same.
Thanks for your time.
Upvotes: 0
Views: 4936
Reputation: 17
Adding to muhammadSalem's answer. This is how I solved my problem by calculating the height of expandableListView's children's total height.
private fun getSubItemTotalHeight(groupPosition: Int): Int {
val children: Int = mAdapter.getChildrenCount(groupPosition)
val desiredWidth: Int = View.MeasureSpec.makeMeasureSpec(mExpandableListView.width,
View.MeasureSpec.UNSPECIFIED)
var subItemTotalHeight = 0
repeat(children) {
val child = mAdapter.getChildView(groupPosition, it, true, null, null)
child.layoutParams = ViewGroup.LayoutParams(
desiredWidth, View.MeasureSpec.UNSPECIFIED)
child.measure(View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED), View.MeasureSpec
.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED))
subItemTotalHeight += child.measuredHeight
}
val dividerCount = children - 1
val dividerTotalCount = (dividerCount * mExpandableListView.dividerHeight).toFloat()
showToast(mExpandableListView.dividerHeight.toString())
val totalDividerPixels = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dividerTotalCount,
resources.displayMetrics
)
return subItemTotalHeight + totalDividerPixels.toInt()
}
One thing to note is that if you added a divider height for your expandableListview, you should include the calculations for it. What I did is convert the total divider height which is in dp into pixels and added it into the totalHeight. This solved the clipping issues I encountered.
Then to use it would be just :
mExpandableListView.setOnGroupExpandListener { groupPosition ->
mExpandableListView.layoutParams.height += getSubItemTotalHeight(groupPosition)
mExpandableListView.requestLayout()
}
mExpandableListView.setOnGroupCollapseListener { groupPosition ->
mExpandableListView.layoutParams.height -= getSubItemTotalHeight(groupPosition)
mExpandableListView.requestLayout()
}
Upvotes: 0
Reputation: 261
I know its late, but if anyone has the same issue. You can solve it by creating a Custom ExpandableListView and using "MeasureSpec.EXACTLY":
public class CustomExpListView extends ExpandableListView{
public CustomExpListView(Context context){
super(context);
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
widthMeasureSpec = MeasureSpec.makeMeasureSpec(960, MeasureSpec.EXACTLY);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(20000, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
Hope this helps to anyone. For me its working.
Upvotes: 0
Reputation: 105
Simply remove the width code and it should work fine.
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
heightMeasureSpec = MeasureSpec.makeMeasureSpec(999999, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
Upvotes: 0
Reputation: 2330
I succeeded in some days ago by doing this. It's a little bit more compact and without any additionnal parameter, and it works perfectly.
public static void setExpandableListViewHeightBasedOnChildren(ExpandableListView expandableListView){
ExpandableNotesListAdapter adapter = (ExpandableNotesListAdapter) expandableListView.getExpandableListAdapter();
if (adapter == null){
return;
}
int totalHeight = expandableListView.getPaddingTop() + expandableListView.getPaddingBottom();
for (int i = 0 ; i < adapter.getGroupCount() ; i++){
View groupItem = adapter.getGroupView(i, false, null, expandableListView);
groupItem.measure(View.MeasureSpec.UNSPECIFIED,View.MeasureSpec.UNSPECIFIED);
totalHeight += groupItem.getMeasuredHeight();
if (expandableListView.isGroupExpanded(i) ){
for( int j = 0 ; j < adapter.getChildrenCount(i) ; j++) {
View listItem = adapter.getChildView(i, j, false, null, expandableListView);
listItem.setLayoutParams(new LayoutParams(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED));
listItem.measure(View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED), View.MeasureSpec
.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
totalHeight += listItem.getMeasuredHeight();
}
}
}
ViewGroup.LayoutParams params = expandableListView.getLayoutParams();
int height = totalHeight + expandableListView.getDividerHeight() * (adapter.getGroupCount() - 1);
if (height < 10)
height = 100;
params.height = height;
expandableListView.setLayoutParams(params);
expandableListView.requestLayout();
}
Don't forget to add this when you init your View, set your adapter, etc. :
Functions.setExpandableListViewHeightBasedOnChildren(listView);
listView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
@Override
public void onGroupExpand(int groupPosition) {
Functions.setExpandableListViewHeightBasedOnChildren(listView);
}
});
Upvotes: 1
Reputation: 578
use this code to calculate expandable list view dynamically:
// calculate the height of expandable listView without expanded
private void setListViewHeight(ExpandableListView expListView) {
ListAdapter listAdapter = expListView.getAdapter();
int totalHeight = 0;
for (int i = 0; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, expListView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
System.out.println("i " + i);
}
ViewGroup.LayoutParams params = expListView.getLayoutParams();
params.height = totalHeight
+ (expListView.getDividerHeight() * (listAdapter.getCount() - 1));
System.out.println("params.height = " + params.height);
expListView.setLayoutParams(params);
expListView.requestLayout();
}
// calculate the height of expandable listview dynamically
private void setListViewHeight(ExpandableListView expListView, int group) {
ExpandableListAdapter listAdapter = expListView
.getExpandableListAdapter();
int totalHeight = 0;
int desiredWidth = MeasureSpec.makeMeasureSpec(expListView.getWidth(),
MeasureSpec.UNSPECIFIED);
for (int i = 0; i < listAdapter.getGroupCount(); i++) {
View groupItem = listAdapter.getGroupView(i, false, null,
expListView);
groupItem.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
totalHeight += groupItem.getMeasuredHeight();
if (((expListView.isGroupExpanded(i)) && (i == group))
|| ((!expListView.isGroupExpanded(i)) && (i == group))) {
for (int j = 0; j < listAdapter.getChildrenCount(i); j++) {
View listItem = listAdapter.getChildView(i, j, false, null,
expListView);
Log.e("Count", listAdapter.getChildrenCount(i) + "");
listItem.setLayoutParams(new ViewGroup.LayoutParams(
desiredWidth, MeasureSpec.UNSPECIFIED));
// listItem.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
listItem.measure(MeasureSpec.makeMeasureSpec(0,
MeasureSpec.UNSPECIFIED), MeasureSpec
.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
totalHeight += listItem.getMeasuredHeight();
System.out.println("totalHeight" + totalHeight);
Log.e("TEST", "gshdkfmjfy,");
}
}
}
ViewGroup.LayoutParams params = expListView.getLayoutParams();
int height = totalHeight
+ (expListView.getDividerHeight() * (listAdapter
.getGroupCount() - 1));
if (height < 10) {
height = 100;
}
params.height = height;
expListView.setLayoutParams(params);
expListView.requestLayout();
}
Upvotes: 2
Reputation: 21
Not sure if you're still looking for an answer, but this is how I did it: pass a reference to the parent view and a height measure (in this case, I used the size of the child list) in the constructor to create the child custom list.
public CustomExpandableList(Context context, View the_parentView, int the_heightMeasure)
{
super(context);
WIDTH = the_parentView!=null?the_parentView.getWidth():LayoutParams.MATCH_PARENT;
HEIGHT = the_heightMeasure * 500;
}
EDIT: Or to make the code more consistent, you could pass the width of the parentView and height measure to the constructor instead of passing the parent view itself. CustomExpandableList(Context the_context, int the_width, int the_heightMeasure)
Upvotes: 2
Reputation: 1603
Create one layout xml file for ParentGroup and ChildParentGroup , another layout xml file for Child. Now you are problem is reduced to two level hierarchy. Then In Expandable listview we have Parent view and childview methods to inflate and use the Parent and Child layouts. So in that mehods you can do whatever you want.
Upvotes: 0