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就是你获取数据后设置的,也就是上面两点的综合