在ScrollView中嵌套ListView
2016-01-05 16:25
453 查看
零用钱的首页面中使用了这种布局,刚开始会疑惑怎么会有这种奇怪的布局,ScrollView和ListView都是滚动结构,按理来说,这两个控件在UI上可以实现相同的功能,ScrollView中只能放一个控件,通常都是LinearLayout,然后在LinearLayout中添加相应的控件来实现滚动效果。
为什么要使用这么奇怪的布局?
1. ScrollView中只能放一个控件,默认情况下Android是禁止在ScrollView中放入另外的ScrollView的,它的高度是无法计算。
2. ScrollView中嵌套了多个ListView,并且作为整体一起滚动,有了这样的设计需求,于是就有了ScrollView嵌套ListView的奇怪结构。
如图所示:
(1)、ListView加载的数据不多,可以完全显示ListView的每一项,那么如果后面还有足够剩余的空间的话,布局B能正常显示;
(2)、ListView加载的数据加多,那么就会导致留给布局B的空间不足,或者根本就没有,布局B将会显示不完全或者完全不显示。
零用钱中则是在滚动布局中添加了三个ListView,我也在代码中尝试过自己在ScrollView中加入ListView,发现ListView的数据加载不全,查了一些资料,对项目中代码有了进一步了解。
调用方法为:
上面这个方法就是设定ListView的高度了,在为ListView设置了Adapter之后使用,就可以解决问题了。但是这个方法有个细节需要注意:
Adapter中getView方法返回的View的必须由LinearLayout组成,因为只有LinearLayout才有measure()方法,如果使用其他的布局如RelativeLayout,在调用
需要手动把ScrollView滚动至最顶端
为什么要使用这么奇怪的布局?
1. ScrollView中只能放一个控件,默认情况下Android是禁止在ScrollView中放入另外的ScrollView的,它的高度是无法计算。
2. ScrollView中嵌套了多个ListView,并且作为整体一起滚动,有了这样的设计需求,于是就有了ScrollView嵌套ListView的奇怪结构。
1. 最简单的布局
如果整个页面只有一个ListView的话,那么由于ListView本身带有滚动效果所以当加载的数据超过页面显示的范围时,可以通过上下滑动来查看所有的item。因此这种情况下,不需要添加ScrollView。2.布局A+ListView
这种情况下,如果布局A定义在ListView的前面,那么当布局A所占的比例较大,或者ListView加载的数据较多时,都会导致ListView显示不完全。同样,由于ListView自身可以滚动,因此仍然可以通过上下滚动来查看ListView的所有item。如图所示:
3.其它布局B+ListView
这种情况下,假设布局B定义在ListView的后面,那么就会出现两种情况:(1)、ListView加载的数据不多,可以完全显示ListView的每一项,那么如果后面还有足够剩余的空间的话,布局B能正常显示;
(2)、ListView加载的数据加多,那么就会导致留给布局B的空间不足,或者根本就没有,布局B将会显示不完全或者完全不显示。
零用钱中则是在滚动布局中添加了三个ListView,我也在代码中尝试过自己在ScrollView中加入ListView,发现ListView的数据加载不全,查了一些资料,对项目中代码有了进一步了解。
设置ListView高度
ListView中的数据是可变的,实际高度需要实际测量。于是需要在代码设置ListView高度的方法。public void setListViewHeightBasedOnChildren(ListView listView) { HomeFragmentAdapter listAdapter = (HomeFragmentAdapter)listView.getAdapter(); if (listAdapter == null) { return; } int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom(); for (int i = 0, len = listAdapter.getCount(); i < len; i++) { // listAdapter.getCount()返回数据项的数目 View listItem = listAdapter.getView(i, null, listView); if (listItem instanceof ViewGroup) { listItem.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); } listItem.measure(0, 0); // 计算子项的高度 totalHeight += listItem.getMeasuredHeight();// 统计所有子项的总高度 } LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); // listView.getDividerHeight()获取子项间分隔符占用的高度 // params.height最后得到整个ListView完整显示需要的高度 // DANGEROUS , NEVER NEVER NEVER NEVER NEVER NEVER NEVER DELETE THIS !!!!!!!!!!!!!!!!!!!!!! Toast.makeText(getActivity(), "i am the point " + params.height, Toast.LENGTH_SHORT); listView.setLayoutParams(params); }
调用方法为:
ListView listView = (ListView) findViewById(id); YourAdapter adapter = new MyAdapter("初始化你的适配器"); listView.setAdapter(adapter); setListViewHeightBasedOnChildren(listView);
上面这个方法就是设定ListView的高度了,在为ListView设置了Adapter之后使用,就可以解决问题了。但是这个方法有个细节需要注意:
Adapter中getView方法返回的View的必须由LinearLayout组成,因为只有LinearLayout才有measure()方法,如果使用其他的布局如RelativeLayout,在调用
listItem.measure(0, 0);时就会抛异常,因为除LinearLayout外的其他布局的这个方法就是直接抛异常的。
需要手动把ScrollView滚动至最顶端
homeScroll.scrollTo(0, 0);
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories