1

在我的布局中,我有两个 ListView 在垂直 LinearLayout 中一个接一个地放置,如下所示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:orientation="vertical"
              android:layout_height="fill_parent">
    <ListView android:id="@+id/events_list"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"/>
    <ListView android:id="@+id/list"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"/>
</LinearLayout>

我想为第一个 ListView onItemClick 事件中的每个元素实现,这将展开每一行以显示附加信息。

为了实现这一点,我决定在初始适配器 getView 函数中添加所有元素,但其中一些元素具有“View.GONE”可见性,然后单击我将它们的可见性更改为可见。

问题是列表元素的初始高度没有扩大,只增加了滚动。

我知道 ExpandableListView,但我从未使用过它,我不知道它是否是这个非常简单的案例的正确解决方案。


我添加到第一个 ListView 的元素布局的摘录(可能有用):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:orientation="horizontal"
              android:layout_height="wrap_content">
...
</LinealLayout>
4

3 回答 3

1

根据您所描述的内容,我认为您需要使用可扩展的列表视图。由于列表视图的工作方式,更新列表中的单个项目很痛苦。ListView最初只会创建尽可能多的视图来填充屏幕,然后在用户滚动列表时回收这些视图。当然,您可以更改值 - 例如更新文本字段和图片 - 但它自己的视图不会每次都重新膨胀,只有子元素的内容发生了变化。这可能就是为什么高度不会改变的原因。适配器正在显示新的子视图,但在原始膨胀列表项的高度内这样做。

我能想到的一种方法是使用 View.INVISIBLE 而不是 View.GONE。这样,您可以放大显示所有元素所需的高度视图,并在有人单击时显示/隐藏。问题是这并没有达到您正在寻找的扩展/收缩状态。再加上它会有很多丑陋的白色空间来隐藏东西。

话虽如此,我不知道将所有这些视图元素设置为消失是个好主意。ExpandableListView旨在使您可以拥有常规视图并在单击时展开不同的视图。这比为每个视图解析可能的 XML 元素然后尝试显示/隐藏 onClick 的不同字段要高效得多。研究使用这种方法。它并不比常规列表视图难多少,并且更适合您想要做的事情。

于 2013-06-27T13:08:37.907 回答
0

我最终使用了非动画技术,如 android 示例应用程序中的折叠列表示例。

基本上,他们更改适配器中的布尔变量并通过发送重新绘制整个列表notifyDatasetChanged()

于 2013-07-15T19:48:12.480 回答
0
public class NestedListView extends ListView implements OnTouchListener, OnScrollListener {

private int listViewTouchAction;
private static final int MAXIMUM_LIST_ITEMS_VIEWABLE = 99;

public NestedListView(Context context, AttributeSet attrs) {
    super(context, attrs);
    listViewTouchAction = -1;
    setOnScrollListener(this);
    setOnTouchListener(this);
}

@Override
public void onScroll(AbsListView view, int firstVisibleItem,
        int visibleItemCount, int totalItemCount) {
    if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
        if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
            scrollBy(0, -1);
        }
    }
}

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int newHeight = 0;
    final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    if (heightMode != MeasureSpec.EXACTLY) {
        ListAdapter listAdapter = getAdapter();
        if (listAdapter != null && !listAdapter.isEmpty()) {
            int listPosition = 0;
            for (listPosition = 0; listPosition < listAdapter.getCount()
                    && listPosition < MAXIMUM_LIST_ITEMS_VIEWABLE; listPosition++) {
                View listItem = listAdapter.getView(listPosition, null, this);
                //now it will not throw a NPE if listItem is a ViewGroup instance
                if (listItem instanceof ViewGroup) {
                    listItem.setLayoutParams(new LayoutParams(
                            LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
                }
                listItem.measure(widthMeasureSpec, heightMeasureSpec);
                newHeight += listItem.getMeasuredHeight();
            }
            newHeight += getDividerHeight() * listPosition;
        }
        if ((heightMode == MeasureSpec.AT_MOST) && (newHeight > heightSize)) {
            if (newHeight > heightSize) {
                newHeight = heightSize;
            }
        }
    } else {
        newHeight = getMeasuredHeight();
    }
    setMeasuredDimension(getMeasuredWidth(), newHeight);
}

@Override
public boolean onTouch(View v, MotionEvent event) {
    if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
        if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
            scrollBy(0, 1);
        }
    }
    return false;
}
于 2018-08-24T11:02:56.500 回答