青岛网站建设
网站首页 联系我们

资讯中心

联系方式
  • 地址:青岛市李沧区金水路772号
  • 电话:0532-87606070
  • 手机:13969865210
  • 邮箱:web@toorain.net

网站开发知识
ScrollView嵌套ListView只显示一行之计算的高度不正确的解决办法
时间:2013-12-19 15:31:34  来源:青岛网站建设  点击:3489

    ScrollView嵌套ListView只显示一行之计算的高度不正确的时候都有哪些解决办法?相信这个问题(ScrollView嵌套ListView只显示一行)的问题相信很多人都遇到过,那么都有什么办法解决呢。

1、解决的核心代码


[html] view plaincopyprint?01.public void setListViewHeightBasedOnChildren(ListView listView) {    
02.        // 获取ListView对应的Adapter    
03.        ListAdapter listAdapter = listView.getAdapter();    
04.        if (listAdapter == null) {    
05.            return;    
06.        }    
07.    
08.        int totalHeight = 0;    
09.        for (int i = 0, len = listAdapter.getCount(); i < len; i++) {    
10.            // listAdapter.getCount()返回数据项的数目    
11.            View listItem = listAdapter.getView(i, null, listView);    
12.            // 计算子项View 的宽高    
13.            listItem.measure(0, 0);     
14.            // 统计所有子项的总高度    
15.            totalHeight += listItem.getMeasuredHeight();     
16.        }    
17.    
18.        ViewGroup.LayoutParams params = listView.getLayoutParams();    
19.        params.height = totalHeight+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));    
20.        // listView.getDividerHeight()获取子项间分隔符占用的高度    
21.        // params.height最后得到整个ListView完整显示需要的高度    
22.        listView.setLayoutParams(params);    
23.    }    
public void setListViewHeightBasedOnChildren(ListView listView) {  
        // 获取ListView对应的Adapter  
        ListAdapter listAdapter = listView.getAdapter();  
        if (listAdapter == null) {  
            return;  
        }  
  
        int totalHeight = 0;  
        for (int i = 0, len = listAdapter.getCount(); i < len; i++) {  
            // listAdapter.getCount()返回数据项的数目  
            View listItem = listAdapter.getView(i, null, listView);  
            // 计算子项View 的宽高  
            listItem.measure(0, 0);   
            // 统计所有子项的总高度  
            totalHeight += listItem.getMeasuredHeight();   
        }  
  
        ViewGroup.LayoutParams params = listView.getLayoutParams();  
        params.height = totalHeight+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));  
        // listView.getDividerHeight()获取子项间分隔符占用的高度  
        // params.height最后得到整个ListView完整显示需要的高度  
        listView.setLayoutParams(params);  
    }   这个代码让控件去计算Listview自己的高度然后设置这个Listview的高度

    但是这个代码里面有一个问题,就是这个当你的ListView里面有多行的TextView的话,ListView的高度就会计算错误,它只算到了一行TextView的高度,

2、最终解决办法

    这个问题很让人头疼了,应该重写一个TextView的onMeasure方法比较好解决,以下是代码。


[java] view plaincopyprint?01.@Override 
02.    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
03.        super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
04. 
05.        Layout layout = getLayout(); 
06.        if (layout != null) { 
07.            int height = (int)FloatMath.ceil(getMaxLineHeight(this.getText().toString())) 
08.                    + getCompoundPaddingTop() + getCompoundPaddingBottom(); 
09.            int width = getMeasuredWidth();             
10.            setMeasuredDimension(width, height); 
11.        } 
12.    } 
13. 
14.    private float getMaxLineHeight(String str) { 
15.        float height = 0.0f; 
16.        float screenW = ((Activity)context).getWindowManager().getDefaultDisplay().getWidth(); 
17.        float paddingLeft = ((LinearLayout)this.getParent()).getPaddingLeft(); 
18.        float paddingReft = ((LinearLayout)this.getParent()).getPaddingRight(); 
19.//这里具体this.getPaint()要注意使用,要看你的TextView在什么位置,这个是拿TextView父控件的Padding的,为了更准确的算出换行  
20. int line = (int) Math.ceil( (this.getPaint().measureText(str)/(screenW-paddingLeft-paddingReft))); height = (this.getPaint().getFontMetrics().descent-this.getPaint().getFontMetrics().ascent)*line; return height;} 
@Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     super.onMeasure(widthMeasureSpec, heightMeasureSpec);

     Layout layout = getLayout();
     if (layout != null) {
         int height = (int)FloatMath.ceil(getMaxLineHeight(this.getText().toString()))
                 + getCompoundPaddingTop() + getCompoundPaddingBottom();
         int width = getMeasuredWidth();           
         setMeasuredDimension(width, height);
     }
 }

 private float getMaxLineHeight(String str) {
  float height = 0.0f;
  float screenW = ((Activity)context).getWindowManager().getDefaultDisplay().getWidth();
  float paddingLeft = ((LinearLayout)this.getParent()).getPaddingLeft();
  float paddingReft = ((LinearLayout)this.getParent()).getPaddingRight();
//这里具体this.getPaint()要注意使用,要看你的TextView在什么位置,这个是拿TextView父控件的Padding的,为了更准确的算出换行
 int line = (int) Math.ceil( (this.getPaint().measureText(str)/(screenW-paddingLeft-paddingReft))); height = (this.getPaint().getFontMetrics().descent-this.getPaint().getFontMetrics().ascent)*line; return height;}

    上面的代码完成更能为,在ListView开始测量时,测量到TextView时,就调用我们的onMeasure方法,我们就可以测量字体的总宽度除与去掉边距的屏幕的大小,就可以算出文字要几行来显示,然后测量字体的高度*行数可以得到字体的总高度,然后在加上上下边距就是TextView真正的高度,然后setMeasuredDimension进去就可以计算出正确的值出来。