scrollview中只能放一个控件,一般都放linearlayout,orientation属性值为vertical。在linearlayout中放需要呈现的内容。listview也在其中,listview的高度设为适应自身内容(wrap_content)。但是为啥在scrollview中嵌套listview会出现只显示第一条listitem的高度呢,原因是:scrollview的ontach方法的滚动事件消费处理,listview控件的高度设定问题
从谷歌那里找到的scrollview嵌套listview只显示一行的解决办法相信很多人都遇到过,然后大部分都是用这位博主的办法解决的吧
刚开始我也是用这个办法解决的,首先感谢这位哥的大私奉献,贴上地址
<a target="_blank" href="http://blog.csdn.net/p106786860/article/details/10461015">http://blog.csdn.net/p106786860/article/details/10461015</a>
2、解决的核心代码
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的高度,
这个问题在so上的概述为以下:
<a target="_blank" href="http://stackoverflow.com/questions/14386584/getmeasuredheight-of-textview-with-wrapped-text">http://stackoverflow.com/questions/14386584/getmeasuredheight-of-textview-with-wrapped-text</a>
3、终极解决办法
这个问题头疼了一阵后,查找了一下,应该重写一个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);
}
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() {
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) {
footerviewattached = true;
public static interface myonitemclicklistener {
public void onitemclick(viewgroup parent, view view, int position,
object o);
这个adapter就是你获取数据后设置的,也就是上面两点的综合