可展开的列表视图嵌套在滚动视图中

12

我有一些关于可展开列表视图的内容。我无法滚动整个布局。我已经搜索了一个多星期,寻找合适的答案。请给出一些建议。


如果你想滚动你的布局,那么你可以在你的布局中使用滚动条。 - Himani
https://dev59.com/r4rda4cB1Zd3GeqPKUgV#46660821 - Ankur Bavishi
我已经解决了相同的问题 > https://dev59.com/r4rda4cB1Zd3GeqPKUgV#46660821 - Ankur Bavishi
1
我用以下方法解决了这个问题:链接 - Ankur Bavishi
9个回答

19
这个解决方案对我有用。当我在导航视图中使用带有LinearLayout的滚动视图的自定义布局时,它能够支持可扩展列表视图。
<android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/nav_header">
    <ScrollView
            android:fillViewport="true"
            android:layout_marginTop="130dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <LinearLayout
                    android:id="@+id/homeLayout"
                    android:clickable="true"
                    android:gravity="center_vertical"
                    android:background="@drawable/layout_click_effect"
                    android:layout_width="match_parent"
                    android:layout_height="45dp">

                    <ImageView
                        android:id="@+id/homeIv"
                        android:layout_width="45dp"
                        android:layout_height="wrap_content"
                        android:src="@mipmap/ic_home_black_24dp" />

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Home" />
                </LinearLayout>
                <View
                    android:background="@android:color/darker_gray"
                    android:layout_width="match_parent"
                    android:layout_height="1dp"/>

                <ExpandableListView
                    android:id="@+id/topCatgExpLv"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="start"
                    android:groupIndicator="@null"
                    android:dividerHeight="1dp" />
        </ScrollView>


    </android.support.design.widget.NavigationView>

在你的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;
        }
    });

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

            }
            //Add Divider Height
            totalHeight += listView.getDividerHeight() * (listAdapter.getChildrenCount(i) - 1);
        }
    }
    //Add Divider Height
    totalHeight += listView.getDividerHeight() * (listAdapter.getGroupCount() - 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();
}

1
对我有用。谢谢。 - Usman Rana
但是它只在我点击可展开列表视图的组项时才起作用。当我滚动视图时,它不起作用。 - S HemaNandhini
@SNandhini 上面的代码 'setListViewHeight' 添加了子项的高度,并且只有在单击组时才显示它,如果您想要展开组并显示其子项,则应手动设置组展开状态,并相应地调用上述 'setListViewHeight' 方法,例如在 for 循环中传递 Exp Listview 和组位置。 - Amit Tumkur
@AmitTumkur,对于多级可展开列表视图(例如3级或4级),它无法正常工作。有什么帮助吗? - KJEjava48
@KJEjava48,您的顶层/第一级可展开视图高度应根据子可展开列表视图的展开/关闭状态进行计算。 - Amit Tumkur

8

你可以很简单地实现这一点。将滚动视图的高度设置为wrap_content。将滚动视图内根视图(比如线性布局)的高度设置为wrap_content,将可展开列表视图的高度也设置为wrap_content。之后,为您的可展开列表视图设置OnGroupExpandListener和OnGroupCollapseListener,并将其高度设置为可展开列表视图的子项高度。代码如下:

你的布局:

<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scrollViewDrawer"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
>
<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="@color/mainGray"
    >
 <ExpandableListView
    android:id="@+id/expandableListCategory"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
                />
 </LinearLayout>
 </ScrollView>

这是你的片段代码:(或者在你的活动中)

public class DrawerFragment extends Fragment implements, OnGroupExpandListener, OnGroupCollapseListener{
ScrollView scrollView;
ExpandableListView expListView;

public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
view rootView = inflater.inflate(R.layout.fragment_layout, container, false);
scrollView = (ScrollView) rootView.findViewById(R.id.scrollViewDrawer);
expListView = (ExpandableListView) rootView.findViewById(R.id.expandableListCategory);
....
}
@Override
public void onGroupExpand(int groupPosition) {
    LinearLayout.LayoutParams param = (LinearLayout.LayoutParams) expListView.getLayoutParams();
    param.height = (childCount * expListView.getHeight());
    expListView.setLayoutParams(param);
    expListView.refreshDrawableState();
    scrollView.refreshDrawableState();
}

@Override
public void onGroupCollapse(int groupPosition) {
    LinearLayout.LayoutParams param = (LinearLayout.LayoutParams) expListView.getLayoutParams();
    param.height = LinearLayout.LayoutParams.WRAP_CONTENT;
    expListView.setLayoutParams(param);
    expListView.refreshDrawableState();
    scrollView.refreshDrawableState();
}

1
在onGroupExpand计算param.height时,我必须将子项数量加1,以考虑到展开后高度为标题和子项高度之和的情况。(这假设标题布局高度和子项标题高度大小相同。) - k2col
嗨,这段代码在可扩展列表视图底部添加了额外的空间。 - pooja majoka
不起作用,我已经尝试了很多方法,比如在另一个XML中包含<layout>,但它没有起作用。 - Sulman Rasheed

3
我知道这个问题已经很老了,但也许对某些人有帮助。基本上我的答案是 Amit Tumkur 和 user2141833 的答案的结合体。经过了很多的尝试和错误,以下代码对我是起作用的:
首先计算可扩展列表视图的初始高度,即在整个列表折叠时的高度。
    for (Integer i = 0; i < mAdapter.getGroupCount(); i++) {
        View groupItem = mAdapter.getGroupView(i, false, null, mExpandableListView);
        groupItem.measure(mExpandableListView.getWidth(), View.MeasureSpec.UNSPECIFIED);
        mInitialHeight += groupItem.getMeasuredHeight();
    }

当点击该组时,将可扩展列表视图的高度设置为“Wrap Content”

    mExpandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
        @Override
        public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
            //Other Expansion/Collapsing Logic
            setListHeightToWrap();
            return true;
        }
    });

setListHeightToWrap是一种不同的方法:

private void setListHeightToWrap() {
    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mExpandableListView.getLayoutParams();
    params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
    mExpandableListView.setLayoutParams(params);
    mExpandableListView.refreshDrawableState();
    mScrollView.refreshDrawableState();
}

然后在OnGroupExpandListener中将可扩展列表视图的高度设置为:

    mExpandableListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
        @Override
        public void onGroupExpand(int groupPosition) {
            LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mStitchingWorksListView.getLayoutParams();
            //The Logic here will change as per your requirements and the height of each of the children in the group
            if (mAdapter.getRealChildrenCount(groupPosition) > 6) {
                params.height = 9 * mInitialHeight;
            } else {
                params.height = 6 * mInitialHeight;
            }
            //For Last Group in the list and the number of children were less as compared to other groups
            if (groupPosition == mAdapter.getGroupCount() - 1) {
                params.height = 3 * mInitialHeight;
            }
            mExpandableListView.setLayoutParams(params);
            mExpandableListView.refreshDrawableState();
        }
    });

同时布局中包含一个ExpandableListView,位于一个LinearLayout和一个ScrollView内部。
希望这能帮助到某些人。 :)

2

首先,我假设你没有在滚动视图中使用多个子布局,因为滚动视图只能有一个直接的子元素。

其次,您不应在滚动视图内使用任何可滚动组件,例如可扩展列表,原因在于此处


2

对于想要在scrollview中使用可扩展列表视图的用户,请使用视图代替可扩展列表,按照以下链接和代码操作:

enter image description here

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

    <LinearLayout
        android:id="@+id/linear_listview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" />

</ScrollView>

在Java类中,有如下的代码 -
for (int i = 0; i < pProductArrayList.size(); i++) {

            LayoutInflater inflater = null;
            inflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View mLinearView = inflater.inflate(R.layout.row_first, null);

            final TextView mProductName = (TextView) mLinearView.findViewById(R.id.textViewName);
            final RelativeLayout mLinearFirstArrow=(RelativeLayout)mLinearView.findViewById(R.id.linearFirst);
            final ImageView mImageArrowFirst=(ImageView)mLinearView.findViewById(R.id.imageFirstArrow);
            final LinearLayout mLinearScrollSecond=(LinearLayout)mLinearView.findViewById(R.id.linear_scroll);

            if(isFirstViewClick==false){
            mLinearScrollSecond.setVisibility(View.GONE);
            mImageArrowFirst.setBackgroundResource(R.drawable.arw_lt);
            }
            else{
                mLinearScrollSecond.setVisibility(View.VISIBLE);
                mImageArrowFirst.setBackgroundResource(R.drawable.arw_down);
            }

            mLinearFirstArrow.setOnTouchListener(new OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {

                    if(isFirstViewClick==false){
                        isFirstViewClick=true;
                        mImageArrowFirst.setBackgroundResource(R.drawable.arw_down);
                        mLinearScrollSecond.setVisibility(View.VISIBLE);

                    }else{
                        isFirstViewClick=false;
                        mImageArrowFirst.setBackgroundResource(R.drawable.arw_lt);
                        mLinearScrollSecond.setVisibility(View.GONE);   
                    }
                    return false;
                } 
            });

这种方法仅适用于少于100个项目的情况,因为如果超过100个项目,应用程序将会在所有项目的填充完成之前冻结。 - MSA

0

在下面输入adapteSet代码

enter code hereListAdapter 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();

0

从API Level 21(棒棒糖)开始,Android SDK正式支持嵌套滚动容器。View和ViewGroup类中有许多方法提供此功能。要使Lollipop上的嵌套滚动工作,您必须通过将android:nestedScrollingEnabled =“true”添加到其XML声明或显式调用setNestedScrollingEnabled(true)来启用子滚动视图的嵌套滚动。


0

请尝试一次。

1)在设置适配器后,请添加此行setExpandableListViewHeight(expandableListViewCategories)。

 expandableListCategoriesAdapter = new ExpandableListCategoriesAdapter(getActivity(), listDataHeader, listDataChild); 
 expandableListViewCategories.setAdapter(expandableListCategoriesAdapter);
 expandableListCategoriesAdapter.notifyDataSetChanged();
 setExpandableListViewHeight(expandableListView);

2) 复制下面的内容并粘贴到setExpandableListViewHeight()方法中。

private void setExpandableListViewHeight(ExpandableListView listView) {
        try {
            ExpandableListAdapter listAdapter = (ExpandableListAdapter) listView.getExpandableListAdapter();
            int totalHeight = 0;
            for (int i = 0; i < listAdapter.getGroupCount(); i++) {
                View listItem = listAdapter.getGroupView(i, false, null, listView);
                listItem.measure(0, 0);
                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();
            scrollBody.post(new Runnable() {
                public void run() {           
                    scrollBody.fullScroll(ScrollView.FOCUS_UP);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

注意:这将自动收起您的可扩展列表视图,您可以滚动查看完整视图。

scrollBody是什么,它没有被识别。 - Amir Dora.

0

尝试了太多解决方案后,我将两个解决方案结合起来,现在它正常工作menuHeight很重要。

  expandableListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
    @Override
    public void onGroupExpand(int groupPosition) {
        LinearLayout.LayoutParams param = (LinearLayout.LayoutParams) 
        expandableListView.getLayoutParams();
        param.height = (2 * menuHeight); //adjust 2 according to you
        expandableListView.setLayoutParams(param);
        expandableListView.refreshDrawableState();
        findViewById(R.id.sv_menu).refreshDrawableState();

    }
});

static int menuHeight =0; // declare globally
public static void setListViewHeightBasedOnChildren(ExpandableListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) return;
int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),
        View.MeasureSpec.UNSPECIFIED);
int totalHeight = 0;
View view = null;
for (int i = 0; i < listAdapter.getCount(); i++) {
    view = listAdapter.getView(i, view, listView);
    if (i == 0) view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, ViewGroup.LayoutParams.WRAP_CONTENT));

    view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
    totalHeight += view.getMeasuredHeight();
}

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

menuHeight = totalHeight;}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接