大多数时候,我们用ListView来加载数据的页面不需要在ListView的外面再套上一个ScollView,因为ListView本身可以滚动显示数据。有时我们页面中除要用ListView显示列表数据之外还要显示其它数据,这时候就需要在整个页面最个层套上一个Scollview,否则显示就可能出现问题(比如在ListView上面已经有很多其它数据,显示在手机上直接导致ListView看不见了,这时就要在整个屏幕布局加ScollView实现滑动界面),用过ScollView嵌套ListView的朋友都知道,在不做任务处理的情况下,ListView的数据只能显示一行多一点点,其它的就看不到了,这个问题怎么解决呢?通常我们可以有下面两种方式:
1,计算高度:(自定义工具类)
import android.view.View; import android.view.ViewGroup; import android.widget.Adapter; import android.widget.ListView; public class ListViewUtils { /*******************************************************************/ //TODO 解决ScollView、GridView及Expandlistview嵌套ListView显示不全问题 /*******************************************************************/ private static int totalHeight = 0; public static void setListViewHeight(ListView listView){ /*得到适配器*/ Adapter adapter = listView.getAdapter(); /*遍历控件*/ for (int i = 0; i < adapter .getCount(); i++) { View view = adapter .getView(i, null, listView); /*测量一下子控件的高度*/ view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); totalHeight+=view.getMeasuredHeight(); } /*控件之间的间隙*/ totalHeight+=listView.getDividerHeight()*(listView.getCount()-1); /*2、赋值给ListView的LayoutParams对象*/ ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight; listView.setLayoutParams(params); } }
这里有一点要注意:我每次调用的时候都会产生在listItem.measure(0,0)报空指针异常。我debug 发现listItem 并不是为空啊,为啥会报错。在经过一番查找之后。我发现原来是自己item的布局用了RelativeLayout 把他换为LinearLayout 就好了。究其原因,原来是 Linearlayout重写了onmeasure方法,其他的布局文件没有重写onmeasure,所以在调用listItem.measure(0, 0); 会报空指针异常,如果想用这个东东,就必须用linearlayout布局喽
2,重写ListView的onMeasure:
import android.content.Context; import android.util.AttributeSet; import android.widget.ListView; public class WholeListView extends ListView { public WholeListView (Context context) { super(context); } public WholeListView (Context context, AttributeSet attrs) { super(context, attrs); } public WholeListView (Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } }
这里解释下onMeasure方法:
onMeasure方法是测量view和它的内容,决定measured width和measured height的这个方法由 measure(int, int)方法唤起,子类可以覆写onMeasure来提供更加准确和有效的测量。其中两个输入参数:widthMeasureSpec,heightMeasureSpec,分别是parent提出的水平和垂直的空间要求。这两个要求是按照View.MeasureSpec类来进行编码的。
参见View.MeasureSpec这个类的说明:这个类包装了从parent传递下来的布局要求,传递给这个child。每一个MeasureSpec代表了对宽度或者高度的一个要求。每一个MeasureSpec有一个尺寸(size)和一个模式(mode)构成。MeasureSpecs这个类提供了把一个的元组包装进一个int型的方法,从而减少对象分配。当然也提供了逆向的解析方法,从int值中解出size和mode。