【问题标题】:Updating layout height on changing element's visibility在更改元素的可见性时更新布局高度
【发布时间】:2018-08-24 19:02:56
【问题描述】:

在我的布局中,我有两个 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>

【问题讨论】:

    标签: android android-listview


    【解决方案1】:

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

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

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

    【讨论】:

    • 谢谢,我会调查的。
    【解决方案2】:

    我最终使用了一种非动画技术,如 android 示例应用中的 Collapsed List 示例。

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

    【讨论】:

      【解决方案3】:
      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;
      }
      

      【讨论】:

      • 你能再解释一下吗?
      • 你必须应用 listview if(List.getVisibility()==View.VISIBLE){ List.setVisibility(View.INVISIBLE) }else{ List.setVisibility(View.VISIBLE) } 在适配器上
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-21
      • 1970-01-01
      • 1970-01-01
      • 2020-02-10
      • 1970-01-01
      相关资源
      最近更新 更多