android scrollview嵌套listview计算高度的问题

简介:  ScrollView中只能放一个控件,一般都放LinearLayout,orientation属性值为vertical。在LinearLayout中放需要呈现的内容。ListView也在其中,ListView的高度设为适应自身内容(wrap_content)。但是为啥在scrollview中嵌套listview会出现只显示第一条listitem的高度呢,原因是:scrollview的

 ScrollView中只能放一个控件,一般都放LinearLayout,orientation属性值为vertical。在LinearLayout中放需要呈现的内容。ListView也在其中,ListView的高度设为适应自身内容(wrap_content)。但是为啥在scrollview中嵌套listview会出现只显示第一条listitem的高度呢,原因是:scrollview的ontach方法的滚动事件消费处理,ListView控件的高度设定问题

从谷歌那里找到的ScrollView嵌套ListView只显示一行的解决办法相信很多人都遇到过,然后大部分都是用这位博主的办法解决的吧

刚开始我也是用这个办法解决的,首先感谢这位哥的大私奉献,贴上地址

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

2、解决的核心代码

 

  1. public void setListViewHeightBasedOnChildren(ListView listView) {     
  2.         // 获取ListView对应的Adapter     
  3.         ListAdapter listAdapter = listView.getAdapter();     
  4.         if (listAdapter == null) {     
  5.             return;     
  6.         }     
  7.      
  8.         int totalHeight = 0;     
  9.         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.     }     
这个代码让控件去计算Listview自己的高度然后设置这个Listview的高度

 

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

这个问题在so上的概述为以下:

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

3、终极解决办法

这个问题头疼了一阵后,查找了一下,应该重写一个TextView的onMeasure方法比较好解决

代码有

 

  1. @Override  
  2.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  3.         super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  4.   
  5.         Layout layout = getLayout();  
  6.         if (layout != null) {  
  7.             int height = (int)FloatMath.ceil(getMaxLineHeight(this.getText().toString()))  
  8.                     + getCompoundPaddingTop() + getCompoundPaddingBottom();  
  9.             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;}  


 

上面的代码完成更能为,在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就是你获取数据后设置的,也就是上面两点的综合

目录
打赏
0
0
0
0
498
分享
相关文章
Android UI设计: 什么是RecyclerView?为什么它比ListView更好?
Android UI设计: 什么是RecyclerView?为什么它比ListView更好?
124 2
Android Studio App入门之列表视图ListView的讲解及实战(附源码 超详细必看)
Android Studio App入门之列表视图ListView的讲解及实战(附源码 超详细必看)
822 1
`RecyclerView`是Android API 21引入的UI组件,用于替代ListView和GridView
【6月更文挑战第26天】`RecyclerView`是Android API 21引入的UI组件,用于替代ListView和GridView。它提供高效的数据视图复用,优化的布局管理,支持多种布局(如线性、网格),并解耦数据、适配器和视图。RecyclerView的灵活性、性能(如局部刷新和动画支持)和扩展性使其成为现代Android开发的首选,特别是在处理大规模数据集时。
106 2
25. 【Android教程】列表控件 ListView
25. 【Android教程】列表控件 ListView
298 2
22. 【Android教程】滚动条 ScrollView
22. 【Android教程】滚动条 ScrollView
131 2
Android 解决TextView多行滑动与NestedScrollView嵌套滑动冲突的问题
Android 解决TextView多行滑动与NestedScrollView嵌套滑动冲突的问题
159 0
如何美化android程序:自定义ListView背景
如何美化android程序:自定义ListView背景
89 2
Android 中ScrollView垂直滚动视图之隐藏滚动条的三种方法
Android 中ScrollView垂直滚动视图之隐藏滚动条的三种方法
219 0
Android控件之高级控件——ListView、cardView、屏幕适配
Android控件之高级控件——ListView、cardView、屏幕适配
103 0
安卓-无敌解决ListView添加标题头无法正常显示的问题(歪门邪道)
安卓-无敌解决ListView添加标题头无法正常显示的问题(歪门邪道)
96 0

热门文章

最新文章

  • 1
    Android历史版本与APK文件结构
    11
  • 2
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
    21
  • 3
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
    13
  • 4
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
    2
  • 5
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    3
  • 6
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    3
  • 7
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    2
  • 8
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
    6
  • 9
    escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
    3
  • 10
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
    1
  • 1
    android FragmentManager 删除所有Fragment 重建
    18
  • 2
    Android实战经验之Kotlin中快速实现MVI架构
    30
  • 3
    即时通讯安全篇(一):正确地理解和使用Android端加密算法
    35
  • 4
    escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
    42
  • 5
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
    142
  • 6
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
    46
  • 7
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    58
  • 8
    Android历史版本与APK文件结构
    159
  • 9
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    48
  • 10
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
    41
  • AI助理

    你好,我是AI助理

    可以解答问题、推荐解决方案等