首先讲一下我遇到的需求吧,页面是这样的,上边有东西,中间是列表,下边还有东西。首先我看到列表立刻就想到了用ListView,但是页面有限,只能用ScrollView包一下。想到就做呗。我就在ScrollView里面加了一个ListView, ListView设置的是wapcontent,这样就出现了ListView数据只显示出了一行。好的,解决问题的方案就来了。
一.设置scrollView中的ListView内容全部显示,不能滑动,将滑动交给scrollView去做。
做法:在设置adapter之前,重新计算ListView的高度,我这里写了一个方法:
- /**
- * 动态设置listView的高度
- * count 总条目
- */
- privatevoid setListViewHeight(ListView listView, BaseAdapter adapter,
- int count) {
- int totalHeight = 0;
- for (int i = 0; i < count; i++) {
- View listItem = adapter.getView(i, null, listView);
- listItem.measure(0, 0);
- totalHeight += listItem.getMeasuredHeight();
- }
- ViewGroup.LayoutParams params = listView.getLayoutParams();
- params.height = totalHeight + (listView.getDividerHeight() * count);
- listView.setLayoutParams(params);
- }
这样做的前提条件是布局文件中ListView的高度要指定,这样才能重新计算,不要设成wapcontent!
二.不全部展示数据,二者皆可滑动。
此方法不用重新计算ListView的高度,只需焦点在Listview上的时候,ScrollView能把滑动权主动交给Listview,这样需要重写ScrollView的一个方法,如下:
- @Override
- publicboolean onInterceptTouchEvent(MotionEvent ev) {
- returnfalse;
- }
这样Scrollview就会根据焦点而让出滑动事件。
三. 不重新计算ListView的高度,展示所有数据,ListView不可滑动。
这个做法是重写ListView的onMeasure方法,如下:
- /**
- * 设置不滚动
- */
- publicvoid onMeasure(int widthMeasureSpec, int heightMeasureSpec)
- {
- int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
- MeasureSpec.AT_MOST);
- super.onMeasure(widthMeasureSpec, expandSpec);
- }
这种方法是同事告诉我的,我没有用过。
做到这里,ScrollView和ListView的问题是解决了,但是ListView的效率问题出现了。
你会发现在ListView的adapter里的getview方法重复执行了很多次,技术使用了缓存技术也是无用的。
有时候数据只有两三个,但是getView方法却被执行了40多次。这样肯定是不行的。但是为什么单独使用ListView的时候却不会出现这种问题呢?
这个原因肯定出在ScrollView和ListView共存上。Google了一下,外国人都不建议他们共存,但是需求是这样的怎么办呢?
我的最终解决方案:自己写一个类似ListView的东西
一. 最初:
- /**
- * 虚拟listview
- *
- * @author JustMe
- *
- */
- publicclass MyListView extends LinearLayout {
- private BaseAdapter adapter;
- private MyOnItemClickListener onItemClickListener;
- /**
- * 通知更新listview
- */
- publicvoid notifyChange() {
- int count = getChildCount();
- LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT,
- LayoutParams.WRAP_CONTENT);
- for (int i = count; i < adapter.getCount(); i++) {
- finalint 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
- publicvoid onClick(View v) {
- if (onItemClickListener != null) {
- onItemClickListener.onItemClick(MyListView.this,
- layout, index, adapter.getItem(index));
- }
- }
- });
- // 每个条目下面的线
- ImageView imageView = new ImageView(getContext());
- imageView.setBackgroundResource(R.drawable.divider_list);
- imageView.setLayoutParams(params);
- layout.addView(v);
- layout.addView(imageView);
- addView(layout, index);
- }
- }
- public MyListView(Context context) {
- super(context);
- initAttr(null);
- }
- public MyListView(Context context, AttributeSet attrs) {
- super(context, attrs);
- initAttr(attrs);
- }
- /**
- * 设置方向
- *
- * @param attrs
- */
- publicvoid initAttr(AttributeSet attrs) {
- setOrientation(VERTICAL);
- }
- public BaseAdapter getAdapter() {
- return adapter;
- }
- /**
- * 设置adapter并模拟listview添加数据
- *
- * @param adpater
- */
- publicvoid setAdapter(BaseAdapter adpater) {
- this.adapter = adpater;
- notifyChange();
- }
- /**
- * 设置条目监听事件
- *
- * @param onClickListener
- */
- publicvoid setOnItemClickListener(MyOnItemClickListener onClickListener) {
- this.onItemClickListener = onClickListener;
- }
- /**
- * 点击事件监听
- *
- * @author JustMe
- *
- */
- publicstaticinterface MyOnItemClickListener {
- publicvoid onItemClick(ViewGroup parent, View view, int position,
- Object o);
- }
- }
这样实现了ListView的最基本的功能,并且提高了效率,例如,全选功能比以上那些方法的速度提高了2-3秒,页面也不卡顿。
缺点是不能一次加载很多的数据,不然数据会显示的很慢,最好分页加载。说到分页,之前都是在ListView上加footerView,在这里也可以做到。
二. 升级:
- publicclass MyListView extends LinearLayout{
- private BaseAdapter adapter;
- private MyOnItemClickListener onItemClickListener;
- boolean footerViewAttached = false;
- private View footerview;
- /**
- * 通知更新listview
- */
- publicvoid 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++) {
- finalint 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
- publicvoid onClick(View v) {
- if (onItemClickListener != null) {
- onItemClickListener.onItemClick(MyListView.this, layout, index,
- adapter.getItem(index));
- }
- }
- });
- ImageView imageView = new ImageView(getContext());
- imageView.setBackgroundResource(R.drawable.divider_list);
- imageView.setLayoutParams(params);
- layout.addView(v);
- layout.addView(imageView);
- addView(layout, index);
- }
- }
- public MyListView(Context context) {
- super(context);
- initAttr(null);
- }
- public MyListView(Context context, AttributeSet attrs) {
- super(context, attrs);
- initAttr(attrs);
- }
- publicvoid initAttr(AttributeSet attrs) {
- setOrientation(VERTICAL);
- }
- /**
- * 初始化footerview
- *
- * @param footerView
- */
- publicvoid initFooterView(final View footerView) {
- this.footerview = footerView;
- }
- /**
- * 设置footerView监听事件
- *
- * @param onClickListener
- */
- publicvoid setFooterViewListener(OnClickListener onClickListener) {
- this.footerview.setOnClickListener(onClickListener);
- }
- public BaseAdapter getAdapter() {
- return adapter;
- }
- /**
- * 设置adapter并模拟listview添加????数据
- *
- * @param adpater
- */
- publicvoid setAdapter(BaseAdapter adpater) {
- this.adapter = adpater;
- removeAllViews();
- if (footerViewAttached)
- addView(footerview);
- notifyChange();
- }
- /**
- * 设置条目监听事件
- *
- * @param onClickListener
- */
- publicvoid setOnItemClickListener(MyOnItemClickListener onClickListener) {
- this.onItemClickListener = onClickListener;
- }
- /**
- * 没有下一页了
- */
- publicvoid noMorePages() {
- if (footerview != null && footerViewAttached) {
- removeView(footerview);
- footerViewAttached = false;
- }
- }
- /**
- * 可能还有下一??
- */
- publicvoid mayHaveMorePages() {
- if (!footerViewAttached && footerview != null) {
- addView(footerview);
- footerViewAttached = true;
- }
- }
- publicstaticinterface MyOnItemClickListener {
- publicvoid onItemClick(ViewGroup parent, View view, int position, Object o);
- }
- }
这样就可以添加footerView了。最终我是使用了这种方案。
原文:http://blog.csdn.net/tianxiangshan/article/details/7956488
相关推荐
利用事件分发机制解决解决ScrollView嵌套ListView使用
解决Scrollview嵌套listview下拉刷新的一些问题
Android ScrollView嵌套ListView嵌套GridView的上下拉以及加载更多
scrollview 与 listview, viewpager 共存
ScrollView嵌套ListView刷新,可深入的学习Scrollview
ScrollView_ListView 事件冲突
ScrollView嵌套ListView,当ListView的顶部到达屏幕顶部时,listView才具有滑动能力,当listView滑动到两端时,会触发ScrollView滑动
主要解决ScrollView与ListView的滑动冲突
很多朋友因项目需求问题需要在ScrollView中嵌套使用ListView或ScrollView 但是彼此的滑动事件会发生冲突,网上大多数都是计算ListView的高度来解决这个问题,但个人亲手尝试 结果ListView的Item要是过多的话ListView...
当ScrollView中嵌套ListView或者GrideView时,listView和GrideView不能完全显示的时候
Android中自定义ListView,解决scrollview嵌套listview 滑动事件冲突,是非常常见的问题,我写了一个例子和大家交流学习
本Demo展示如何在ScrollView中嵌套ListView,通过自定义ListView有效解决冲突问题
android中scrollview与listview共存,内含源码导入Eclipse直接即可使用
解决ScrollView嵌套ListView显示不全及其他BUG问题;自定义ScrollView及自定义ListView
scrollview+listview 安卓,四种方法的解决
android 解决ScrollView和listView嵌套冲突问题(保证在ScrollView中滑动listView只响应listView的滑动)
项目需要,特地查看了Android事件拦截机制,实现了ScrollView嵌套ListView,通过重写ScrollView的onInterceptTouchEvent()方法,同时支持动态设置,比如支持设置下拉拦截,刷新拦截。
弹性拉伸Scrollview、scrollview嵌套listview和scrollview滑动监听demo
ScrollView+listView指定坐标;重写ScrollView和Listview;在当前页面有三个标题内容并且只允许上下的滑动,当浏览页面滑动到某一个标题的时候,在顶部的大标题会被选中;
用于解决scrollview组件嵌套listview组件时候 两者之间的冲突问题