android scrollview嵌套listview計算高度的問題

 ScrollView中只能放一個控件,通常都放LinearLayout,orientation屬性值爲vertical。在LinearLayout中放須要呈現的內容。ListView也在其中,ListView的高度設爲適應自身內容(wrap_content)。可是爲啥在scrollview中嵌套listview會出現只顯示第一條listitem的高度呢,緣由是:scrollview的ontach方法的滾動事件消費處理,ListView控件的高度設定問題app

從谷歌那裏找到的ScrollView嵌套ListView只顯示一行的解決辦法相信不少人都遇到過,而後大部分都是用這位博主的辦法解決的吧ide

剛開始我也是用這個辦法解決的,首先感謝這位哥的大私奉獻,貼上地址字體

http://blog.csdn.net/p106786860/article/details/10461015this

二、解決的核心代碼.net

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的高度blog

可是這個代碼裏面有一個問題,就是這個當你的ListView裏面有多行的TextView的話,ListView的高度就會計算錯誤,它只算到了一行TextView的高度,事件

這個問題在so上的概述爲如下:rem

http://stackoverflow.com/questions/14386584/getmeasuredheight-of-textview-with-wrapped-textget

三、終極解決辦法it

這個問題頭疼了一陣後,查找了一下,應該重寫一個TextView的onMeasure方法比較好解決

代碼有

@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進去就能夠計算出正確的值出來。

完整大代碼我貼出來

public class MyListView2 extends LinearLayout { private BaseAdapter adapter; private MyOnItemClickListener onItemClickListener; boolean footerViewAttached = false; private View footerview; @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // TODO Auto-generated method stub super.onLayout(changed, l, t, r, b); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } public void notifyChange() { int count = getChildCount(); if (footerViewAttached) { count--; } LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT); for (int i = count; i < adapter.getCount(); i++) { final int index = i; final LinearLayout layout = new LinearLayout(getContext()); layout.setLayoutParams(params); layout.setOrientation(VERTICAL); View v = adapter.getView(i, null, null); v.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (onItemClickListener != null) { onItemClickListener.onItemClick(MyListView2.this, layout, index, adapter.getItem(index)); } } }); ImageView imageView = new ImageView(getContext()); imageView.setLayoutParams(params); layout.addView(v); layout.addView(imageView); addView(layout, index); } } public MyListView2(Context context) { super(context); initAttr(null); } public MyListView2(Context context, AttributeSet attrs) { super(context, attrs); initAttr(attrs); } public void initAttr(AttributeSet attrs) { setOrientation(VERTICAL); } public void initFooterView(final View footerView) { this.footerview = footerView; } public void setFooterViewListener(OnClickListener onClickListener) { this.footerview.setOnClickListener(onClickListener); } public BaseAdapter getAdapter() { return adapter; } public void setAdapter(BaseAdapter adpater) { this.adapter = adpater; removeAllViews(); if (footerViewAttached) addView(footerview); notifyChange(); } public void setOnItemClickListener(MyOnItemClickListener onClickListener) { this.onItemClickListener = onClickListener; } public void noMorePages() { if (footerview != null && footerViewAttached) { removeView(footerview); footerViewAttached = false; } } public void mayHaveMorePages() { if (!footerViewAttached && footerview != null) { addView(footerview); footerViewAttached = true; } } public static interface MyOnItemClickListener { public void onItemClick(ViewGroup parent, View view, int position, Object o); } }

這個adapter就是你獲取數據後設置的,也就是上面兩點的綜合

相關文章
相關標籤/搜索