ExpandableListView动态子高度

时间:2016-11-04 13:45:10

标签: android height expandablelistview expandablelistadapter

我有一个ExpandableListView位于LinearLayout容器内,并使用CustomAdapter进行设置。
对于它的孩子,我使用onGroupClick()方法向特定服务发送请求并将结果作为String,然后填充点击组项的子列表。

问题,因为我无法获得更新的高度(在服务响应设置为子视图的文本视图的文本视图之后),linearlayout容器高度不会增加它应该的方式。它还会产生滚动问题。

虽然列表子项xml是WRAP_CONTENT,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/rowHeight"
android:background="@color/colorLightYellow">

<TextView
    android:id="@+id/tvTitle"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_marginLeft="@dimen/marginGeneral"
    android:layout_toLeftOf="@+id/tvCount"
    android:gravity="center_vertical"
    android:paddingBottom="@dimen/marginGeneral"
    android:paddingTop="@dimen/marginGeneral"
    android:text="tvTitle"
    android:textColor="@color/colorGray"
    android:textSize="@dimen/fontSizeNormal" />
...
</RelativeLayout>

因此,代码部分与我长期待在一起:

@Override
public boolean onGroupClick(ExpandableListView parent, View v, final int groupPosition, long id) {
    Map<Item, List<ItemDetail>> childList = detailExpandableAdapter.getChildList();
    final Item item = detailExpandableAdapter.getGroup(groupPosition);
    if (childList.get(item).size() == 0) {
        startProgressDialog();

        GlobalApplication.getService().getItemDetails(Session.getCurrent().getSessionId(), getItem.item.itemNo, item.name, new ServiceCallback<GetItemDetails>() {
            @Override
            public void onSuccess(GetItemDetails response) {
                stopProgressDialog();

                List<ItemDetail> itemDetailList = null;

                if (GetItemDetails.isSuccess(response)) {
                    itemDetailList = response.getItemDetailList();
                } else {
                    itemDetail itemDetail = new ItemDetail();
                    itemDetail.resultDesc = response.getResult().getResultDesc();

                    if (StringUtils.isNullOrWhitespace(itemDetail.resultDesc)) {
                        itemDetail.resultDesc = Result.getGeneralFailResult().getResultDesc();
                    }

                    itemDetailList = new ArrayList<ItemDetail>();
                    itemDetailList.add(itemDetail);
                }

                if (itemDetailList != null) {
                    Map<Item, List<ItemDetail>> childList = detailExpandableAdapter.getChildList();

                    if (childList.containsKey(item)) {
                        childList.remove(item);
                    }
                    childList.put(item, itemDetailList);

                    detailExpandableAdapter.setChildList(childList);
                    detailExpandableAdapter.notifyDataSetChanged();
                    detailExpandableAdapter.notifyDataSetInvalidated();

                    listViewLastItems.expandGroup(groupPosition);
                }
            }

            @Override
            public void onFail() {
                stopProgressDialog();
            }
        });

        return false;
    }

    return false;
}

@Override
public void onGroupExpand(int groupPosition) {
    setExpandableListViewHeightStable(listViewLastItems, llListViewItemDetailContainer);
    if (lastExpanded != -1 && groupPosition != lastExpanded)
        listViewItems.collapseGroup(lastExpanded);
    lastExpanded = groupPosition;
}

public void setExpandableListViewHeight(ExpandableListView expandableListView, LinearLayout linearLayoutParent){
    try {
        ExpandableListAdapter expandableListAdapter = expandableListView.getExpandableListAdapter();

        int totalHeight = 0;
        int desiredWidth = View.MeasureSpec.makeMeasureSpec(expandableListView.getWidth(), View.MeasureSpec.UNSPECIFIED);

        for (int i = 0; i < expandableListAdapter.getGroupCount(); i++) {
            View groupItem = expandableListAdapter.getGroupView(i, false, null, expandableListView);
            groupItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);

            //Logger.debug("recalculateExpandableListViewHeight listItem:"+groupItem.getMeasuredHeight());
            totalHeight += groupItem.getMeasuredHeight();

            if (expandableListView.isGroupExpanded(i)){
                for (int j = 0; j < expandableListAdapter.getChildrenCount(i); j++) {
                    View listItemChild = expandableListAdapter.getChildView(i, j, false, null, expandableListView);

                    listItemChild.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, View.MeasureSpec.UNSPECIFIED));
                    listItemChild.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));

                    Logger.debug("recalculateExpandableListViewHeight listItemChild:" + listItemChild.getMeasuredHeight());
                    totalHeight += listItemChild.getMeasuredHeight();
                }
            }
        }

        linearLayoutParent.getLayoutParams().height = totalHeight + (expandableListAdapter.getGroupCount() * expandableListView.getDividerHeight());
        linearLayoutParent.requestLayout();
    } catch (Exception e) {
        Logger.printStackTrace(e);
    }
}  

更新:这是我用作容器的线性布局

<LinearLayout
                android:id="@+id/llListViewItemContainer"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/tvItemDueDate"
                android:layout_marginTop="@dimen/marginGeneral"
                android:orientation="vertical"/>

更新2:我正在动态地将ExpandableListView添加到LinearLayout。

listViewItems = new ExpandableListView(getContext());
listViewItems.setScrollContainer(false);
listViewItems.setDivider(new ColorDrawable(getResources().getColor(R.color.colorLightGray)));
listViewItems.setDividerHeight(UIHelper.convertDptoPixels(1));
listViewItems.setGroupIndicator(null);
listViewItems.setOnGroupClickListener(this);
listViewItems.setOnGroupExpandListener(this);
listViewItems.setOnGroupCollapseListener(this);
//generate empty child list
Map<Item, List<ItemDetail>> childMap = new HashMap<>();
for (Item item : getItems.getItemList()) {
    childMap.put(item, new ArrayList<ItemDetail>());
                }
detailExpandableAdapter = new detailExpandableAdapter(getActivity(), getItems.getItemList(), childMap);
listViewItems.setAdapter(detailExpandableAdapterF);
listViewItems.removeAllViews();
listViewItems.addView(listViewLastItems);
UIHelper.setExpandableListViewHeightStable(listViewItems, llListViewDetailContainer);

2 个答案:

答案 0 :(得分:4)

使用下面给定的自定义ExpandableListView类并覆盖onMeasure方法。

public class MyExpandableListView extends ExpandableListView {

    public MyExpandableListView(Context context) {
        super(context);
    }

    public MyExpandableListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyExpandableListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
                Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
        ViewGroup.LayoutParams params = getLayoutParams();
        params.height = getMeasuredHeight();
    }
}

并使用它,

<com.app.custom.NonScrollExpandableListView 

    android:layout_width="match_parent"
    android:layout_height="wrap_content" /> 

com.app.custom 替换为您放置此自定义类的包名。

如果可能,请使用NestedScrollView代替ScrollView,因为它支持在新旧版本的Android上充当嵌套滚动父级和子级。默认情况下启用嵌套滚动。

请告诉我这是否对您有所帮助。快乐的编码!!!

答案 1 :(得分:0)

我建议您使用 ExpandableListView HeaderView 属性。 AS ExpandableListView ListView 的派生类,因此我认为HeaderView属性必须存在。

在ScrollView中使用ListView的问题 -

  1. 性能 - 如果你打算使用ListView的测量属性,它肯定会影响细胞的回收。
  2. 用户体验 - 当ListView的父级是另一个可滚动视图时,会出现奇怪的行为。
  3. 最好将LinearLayout内容移动到另一个视图中,然后根据需要将该视图放大并放入ListView的 Header Footer

     // Inflated View which is going to be use as Header of view
      ViewGroup headerView = (ViewGroup)getLayoutInflater().inflate(R.layout.list_header,expListView,false);
      // Add that view to Header
      your_expandale_listView.addHeaderView(headerView);