计算列表视图的大小或如何告诉它完全展开

我目前正在尝试使用ScrollView内的ListView。 我知道从我读过的,这是看不起,但我想通过显示其所有行,以便无需滚动完全展开ListView展开。 然而,我一直在努力,告诉ListView完全展开以显示所有的行,因为它需要一个定义的高度。 有没有人知道一种方法来计算完全展开后的ListView的高度,然后绘制?

这个问题主要源于这样一个事实,即不能在另一个可滚动视图内放置一个可滚动的视图。 我很好,事实上,ListView将无法滚动,只要我可以使其展开显示其所有行。 但是,我无法做到这一点,因为没有能够给它一个确定的高度,这似乎我需要计算。

看到一个草图下面的url(我是一个新用户,所以我不能发表一个)。 它显示我的整个布局对于“物理”屏幕来说太大,并且需要滚动以显示底部的列表和button的其余部分。 我试图弄清楚,“虚拟”屏幕太大,无法在一个屏幕上,即使没有ListView那里。

http://img51.imageshack.us/img51/7210/screenmockup.png

那么,感谢鲁迪,他的build议非常有帮助。 这是如何实现的。

1)创build一个扩展ListView的新类:

package com.example.android.views; import android.content.Context; import android.graphics.Canvas; import android.util.AttributeSet; import android.widget.ListView; public class ExpandedListView extends ListView { private android.view.ViewGroup.LayoutParams params; private int old_count = 0; public ExpandedListView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { if (getCount() != old_count) { old_count = getCount(); params = getLayoutParams(); params.height = getCount() * (old_count > 0 ? getChildAt(0).getHeight() : 0); setLayoutParams(params); } super.onDraw(canvas); } } 

2)…最后添加新的视图到你的xml布局文件:

 <com.example.android.views.ExpandedListView android:id="@+id/list" android:layout_width="wrap_content" android:layout_height="wrap_content" android:scrollbars="none" android:padding="0px" /> 

计算高度的正确方法是:

 int height = 0; for (int i = 0; i < listView.getChildCount(); i++) { height += listView.getChildAt(i).getMeasuredHeight(); height += listView.getDividerHeight(); } 

注意! 正确的方法来计算高度不是

 params.height = getCount() * (old_count > 0 ? getChildAt(0).getHeight() : 0); 

我们必须增加每个(一个)分隔高度的高度。

 if(oldCount > 0 && getCount() > 0) params.height = getCount() * (getChildAt(0).getHeight() + getDividerHeight()) - getDividerHeight(); else params.height = 0; 

如果你想要一个不滚动的ListView,你不能只使用LinearLayout?

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

你不应该把你的ListView放在ScrollView中。 ListView已经可以滚动了。

如果它是布局中唯一的东西,ListView应该默认完全展开。

如果它不是布局中唯一的东西,并且您希望ListView展开以占用所有可用空间,请将ListView上的layout_weight设置为1,其中layout_weight = 0。

 <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" orientation="vertical"> <TextView id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <ListView id="@+id/listView" android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1"/> </LinearLayout> 

编辑:ListView实际上是devise成可滚动的…你在屏幕截图中的屏幕布局并不像“android的方式”。

然而,如果你真的想要绕过这个,你可以尝试膨胀其中的一行,得到它的minHeight,然后乘以ListView适配器中的项数。

 LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); View view = inflater.inflate(R.layout.label_value_row, null, false); int height = adapter.getCount() * view.getMinHeight(); 

我从djunod的答案(静态类中的函数)

计算列表视图的大小

并改变提取方法如下。 它在删除操作成功后工作。

这是我的最后一堂课

类ExpandedListViewinheritanceListView {

 private android.view.ViewGroup.LayoutParams params; private int old_count = 0; public ExpandedListView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { if (getCount() != old_count) { params = getLayoutParams(); old_count = getCount(); int totalHeight = 0; for (int i = 0; i < getCount(); i++) { this.measure(0, 0); totalHeight += getMeasuredHeight(); } params = getLayoutParams(); params.height = totalHeight + (getDividerHeight() * (getCount() - 1)); setLayoutParams(params); } super.onDraw(canvas); } 

}

现在我的列表视图扩大后行插入没有滚动。 并在行后删除此代码为listview计算正确的大小。 我不知道它是如何工作的。 但它正在工作。 BR

我一直在研究如何做到这一点,虽然这个问题已经得到解答,但我想提供一个我认为更好的解决scheme:

查看ListView的源代码,您可以在onMeasure(…)代码中看到以下内容:

 if (heightMode == MeasureSpec.AT_MOST) { // TODO: after first layout we should maybe start at the first visible position, not 0 heightSize = measureHeightOfChildren(widthMeasureSpec, 0, NO_POSITION, heightSize, -1); } 

因此,只需调用listView的度量,并传递MeasureSpec.AT_MOST作为高度,而不是通常的MeasureSpec.UNSPECIFIED。

我做了以下测量一个列表视图,并将其放置在popup式窗口中:

  int widthMeasureSpec = MeasureSpec.makeMeasureSpec(displayMetrics.widthPixels, MeasureSpec.EXACTLY); int heightMeasureSpec = MeasureSpec.makeMeasureSpec(displayMetrics.heightPixels, MeasureSpec.AT_MOST); mCatalogView.measure(widthMeasureSpec, heightMeasureSpec); mPopup.setWidth(mCatalogView.getMeasuredWidth()); mPopup.setHeight(mCatalogView.getMeasuredHeight()); 

我最终重写了ListView的onDraw() ,并计算视图中可见行的平均高度,然后根据适配器中有多less项目来估计列表的实际高度。 这个估计发生了几次,直到所有的行都可见。

我知道这是迟到,已经有了答案,但如果你真的想这样做,有一个简单的方法:

创build具有定义高度的列表视图项目

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="100dp" android:orientation="horizontal" > <ImageView android:id="@+id/lvItemSurpriseMeImgRestaurant" android:layout_width="80dp" android:layout_height="80dp" android:layout_marginLeft="5dp" android:contentDescription="@string/restaurantImageDescriptionColon" /> </LinearLayout> 

现在我们知道Item是100dp高,如果我们知道项目的数量,那么它非常简单

ListView高度字面上设置为NoOfItems * Height + 10dp extra的值

因为所有的单位都在dp所以永远不会改变。

如果你有多个项目types,然后用基本的math计算并设置它

  <ListView android:id="@+id/menuListView" android:layout_width="match_parent" android:layout_height="210dp" android:layout_weight="1.0" tools:ignore="NestedScrolling" tools:listitem="@layout/menu_item" > </ListView> 

如果你有不同高度的物品,你需要使用这个方法:

 public void setListViewHeightBasedOnChildren(ListView listView) { ListAdapter listAdapter = listView.getAdapter(); if (listAdapter != null) { int numberOfItems = listAdapter.getCount(); // Get total height of all items. int totalItemsHeight = 0; for (int itemPos = 0; itemPos < numberOfItems; itemPos++) { View item = listAdapter.getView(itemPos, null, listView); float px = 300 * (listView.getResources().getDisplayMetrics().density); item.measure( View.MeasureSpec.makeMeasureSpec((int)px, View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); int height = item.getMeasuredHeight(); totalItemsHeight += height; } // Get total height of all item dividers. int totalDividersHeight = listView.getDividerHeight() * (numberOfItems - 1); // Set list height. ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalItemsHeight + totalDividersHeight; listView.setLayoutParams(params); listView.requestLayout(); } } 

它与任何ListView与任何项目工作得很好

使用这将工作:

 public class ListViewEx extends ListView { public ListViewEx(Context context) { super(context); } /** * @param context * @param attrs */ public ListViewEx(Context context, AttributeSet attrs) { super(context, attrs); } /** * 设置不滚动*/ public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { return ev.getAction()==MotionEvent.ACTION_MOVE||super.dispatchTouchEvent(ev); } 

}