ExpandableListView inside a scrollview

2019-03-31 19:16发布

问题:

In my app i want to make a page that have ExpandableListView and below him CheckBox.

My problem is that my ExpandableListView is too big and make the CheckBox out of the page.

On smaller screens is not visible at all.

I tried to put ExpandableListView inside scrollview but its not working.

Is there a way to make my design?

Here is my code and a screenshot.

XML code:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/White" >

    <ScrollView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:fillViewport="true" >

        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" >

            <TextView
                android:id="@+id/textView1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
                android:layout_marginTop="15sp"
                android:text="In this page you can save a group of exercise under one routine."
                android:textColor="@color/Black"
                android:textSize="20sp" />

            <ExpandableListView
                android:id="@+id/instructionsExView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_below="@+id/textView1"
                android:layout_marginTop="15sp" >
            </ExpandableListView>

            <TextView
                android:id="@+id/textView2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/instructionsExView"
                android:layout_marginTop="15sp"
                android:text="If you want to open the instruction again check &apos;need help?&apos;"
                android:textColor="@color/Black"
                android:textSize="20sp" />

            <CheckBox
                android:id="@+id/checkInstructions"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_below="@+id/textView2"
                android:layout_marginTop="16dp"
                android:checked="false"
                android:text="dont show again when opening the page"
                android:textColor="@color/Black" />

        </RelativeLayout>
    </ScrollView>

</RelativeLayout>

Screen shot:

EDIT:

回答1:

in your "onCreate" method write: "setListViewHeight(expListView)" after "expListView.setAdapter(listAdapter)" then set OnGroupClickListener for your expandable list view as below:

expListView.setOnGroupClickListener(new OnGroupClickListener() {

        @Override
        public boolean onGroupClick(ExpandableListView parent, View v,
                int groupPosition, long id) {
            setListViewHeight(parent, groupPosition);
            return false;
        }
    });

used methods:

private void setListViewHeight(ListView listView) {
    ListAdapter listAdapter = listView.getAdapter();
    int totalHeight = 0;
    for (int i = 0; i < listAdapter.getCount(); i++) {
    View listItem = listAdapter.getView(i, null, listView);
    listItem.measure(0, 0);
    totalHeight += listItem.getMeasuredHeight();
    }

    ViewGroup.LayoutParams params = listView.getLayoutParams();
    params.height = totalHeight
    + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
    listView.setLayoutParams(params);
    listView.requestLayout();
    }


    private void setListViewHeight(ExpandableListView listView,
    int group) {
    ExpandableListAdapter listAdapter = (ExpandableListAdapter) listView.getExpandableListAdapter();
    int totalHeight = 0;
    int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(),
    MeasureSpec.EXACTLY);
    for (int i = 0; i < listAdapter.getGroupCount(); i++) {
    View groupItem = listAdapter.getGroupView(i, false, null, listView);
    groupItem.measure(desiredWidth, 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, 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();

    }

now u are good to go.



回答2:

Based on @Dmila Ram`s answer, I was able to do it.

In my case, I initialize and populate the ExpandableListView in the onCreate method like so:

expandableListView = (ExpandableListView) findViewById(R.id.appsMenu);
listAdapter = new ExpandableListAdapter(this, listDataHeader, listDataChild);
expandableListView.setAdapter(listAdapter);
for (int i = 0; i < listAdapter.getGroupCount(); i++)
     expandableListView.expandGroup(i);
setListViewHeight(expandableListView);
expandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
     @Override
     public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
          setListViewHeight(parent, groupPosition);
          return false;
        }
     });

Notice that I expand each group. After that I call setListViewHeight(expandableListView);

This method is responsible for calculating the height of the ExpandableListView when it is created for first time.

Here is the code:

private void setListViewHeight(ExpandableListView listView) {
        ExpandableListAdapter listAdapter = (ExpandableListAdapter) listView.getExpandableListAdapter();
        int totalHeight = 0;
        for (int i = 0; i < listAdapter.getGroupCount(); i++) {
            View groupView = listAdapter.getGroupView(i, true, null, listView);
            groupView.measure(0, View.MeasureSpec.UNSPECIFIED);
            totalHeight += groupView.getMeasuredHeight();

        if (listView.isGroupExpanded(i)){
            for(int j = 0; j < listAdapter.getChildrenCount(i); j++){
                View listItem = listAdapter.getChildView(i, j, false, null, listView);
                listItem.measure(0, View.MeasureSpec.UNSPECIFIED);
                totalHeight += listItem.getMeasuredHeight();
            }
        }
    }

    ViewGroup.LayoutParams params = listView.getLayoutParams();
    params.height = totalHeight
            + (listView.getDividerHeight() * (listAdapter.getGroupCount() - 1));
    listView.setLayoutParams(params);
    listView.requestLayout();
}

It's really not necessary to have the groups expanded, instead we can just loop through the child items and add them to the calculation of the total height.

This will make all widgets in the ScrollView scrollable and it will also show the ExpandableListView properly.

Then we also need this method, to make sure that clicking on the groups will calculate the height as well:

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();
}

That's pretty much it, then it works fine, but this solution can be optimized even further.



回答3:

you cant use listview inside scroll view ,so you should use scroll view and add the rows as views dynamically.



回答4:

You do not need more than one RelativeLayout, because expandablelistview should be between two items (in your case), these two items are going to be the first ones with parentTop and parentBottom, the rest will be positioned playing with above/below.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/White"
android:orientation="vertical" >

<TextView
    android:id="@+id/textView1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_marginTop="15sp"
    android:text="In this page you can save a group of exercise under one routine."
    android:textColor="@color/Black"
    android:textSize="20sp" />

<CheckBox
    android:id="@+id/checkInstructions"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_marginTop="16dp"
    android:checked="false"
    android:text="dont show again when opening the page"
    android:textColor="@color/Black" />

<TextView
    android:id="@+id/textView2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_above="@+id/checkInstructions"
    android:layout_marginTop="15sp"
    android:text="If you want to open the instruction again check &apos;need help?&apos;"
    android:textColor="@color/Black"
    android:textSize="20sp" />

<ExpandableListView
    android:id="@+id/instructionsExView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_above="@+id/textView2"
    android:layout_below="@id/textView1"
    android:layout_marginTop="15sp" >
</ExpandableListView>

</RelativeLayout>


回答5:

You can use below code to achieve this thing. I used ListViewyou can replace with ExpandableListView

<?xml version="1.0" encoding="utf-8"?>

<TextView
    android:id="@+id/textView1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_marginTop="15sp"
    android:text="In this page you can save a group of exercise under one routine."
    android:textColor="@color/WHITE"
    android:textSize="20sp" />

<ListView
    android:id="@+id/listView1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_weight="2" >

</ListView>

<TextView
    android:id="@+id/textView2"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="15sp"
    android:text="If you want to open the instruction again check &apos;need help?&apos;"
    android:textColor="@color/WHITE"
    android:textSize="20sp" />

<CheckBox
    android:id="@+id/checkInstructions"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_below="@+id/textView2"
    android:layout_marginBottom="20dp"
    android:layout_marginTop="16dp"
    android:checked="false"
    android:text="dont show again when opening the page"
    android:textColor="@color/WHITE" />

I checked the above code with around 50 listitem value and tested on a very small display device and it works fine.

<?xml version="1.0" encoding="utf-8"?>

<TextView
    android:id="@+id/textView1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_marginTop="15sp"
    android:text="In this page you can save a group of exercise under one routine."
    android:textColor="@color/WHITE"
    android:textSize="20sp" />

<ExpandableListView
    android:id="@+id/expandableListView1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_weight="2" >

</ExpandableListView>

<TextView
    android:id="@+id/textView2"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="15sp"
    android:text="If you want to open the instruction again check &apos;need help?&apos;"
    android:textColor="@color/WHITE"
    android:textSize="20sp" />

<CheckBox
    android:id="@+id/checkInstructions"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_below="@+id/textView2"
    android:layout_marginBottom="20dp"
    android:layout_marginTop="16dp"
    android:checked="false"
    android:text="dont show again when opening the page"
    android:textColor="@color/WHITE" />

I checked with ExpandableListView and it working fine for me.