ScrollView下,ListView生存之道

首先讲一下我遇到的需求吧,页面是这样的,上边有东西,中间是列表,下边还有东西。首先我看到列表立刻就想到了用ListView,但是页面有限,只能用ScrollView包一下。想到就做呗。我就在ScrollView里面加了一个ListView, ListView设置的是wapcontent,这样就出现了ListView数据只显示出了一行。好的,解决问题的方案就来了。

一.设置scrollView中的ListView内容全部显示,不能滑动,将滑动交给scrollView去做

做法:在设置adapter之前,重新计算ListView的高度,我这里写了一个方法:

/**
	 * 动态设置listView的高度
	 * count 总条目
	 */
	private void 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
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		return false;
	}

这样Scrollview就会根据焦点而让出滑动事件。

三.  不重新计算ListView的高度,展示所有数据,ListView不可滑动。

这个做法是重写ListView的onMeasure方法,如下:

/**
	 * 设置不滚动
	 */
	public void 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
 * 
 */
public class MyListView extends LinearLayout {
	
	private BaseAdapter adapter;
	private MyOnItemClickListener onItemClickListener;

	/**
	 * 通知更新listview
	 */
	public void notifyChange() {
		int count = getChildCount();
		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(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
	 */
	public void initAttr(AttributeSet attrs) {
		setOrientation(VERTICAL);
	}

	


	public BaseAdapter getAdapter() {
		return adapter;
	}

	/**
	 * 设置adapter并模拟listview添加数据
	 * 
	 * @param adpater
	 */
	public void setAdapter(BaseAdapter adpater) {
		this.adapter = adpater;


		notifyChange();

	}

	/**
	 * 设置条目监听事件
	 * 
	 * @param onClickListener
	 */
	public void setOnItemClickListener(MyOnItemClickListener onClickListener) {
		this.onItemClickListener = onClickListener;
	}



	/**
	 * 点击事件监听
	 * 
	 * @author JustMe
	 * 
	 */
	public static interface MyOnItemClickListener {
		public void onItemClick(ViewGroup parent, View view, int position,
				Object o);

	}
}
这样实现了ListView的最基本的功能,并且提高了效率,例如,全选功能比以上那些方法的速度提高了2-3秒,页面也不卡顿。

缺点是不能一次加载很多的数据,不然数据会显示的很慢,最好分页加载。说到分页,之前都是在ListView上加footerView,在这里也可以做到。

二. 升级:

public class MyListView  extends LinearLayout{
	private BaseAdapter adapter;
	private MyOnItemClickListener onItemClickListener;
	boolean footerViewAttached = false;
	private View footerview;

	/**
	 * 通知更新listview
	 */
	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(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);
	}

	public void initAttr(AttributeSet attrs) {

		setOrientation(VERTICAL);
	}

	/**
	 * 初始化footerview
	 * 
	 * @param footerView
	 */
	public void initFooterView(final View footerView) {
		this.footerview = footerView;
	}

	/**
	 * 设置footerView监听事件
	 * 
	 * @param onClickListener
	 */
	public void setFooterViewListener(OnClickListener onClickListener) {
		this.footerview.setOnClickListener(onClickListener);
	}

	public BaseAdapter getAdapter() {
		return adapter;
	}

	/**
	 * 设置adapter并模拟listview添加�?��数据
	 * 
	 * @param adpater
	 */
	public void setAdapter(BaseAdapter adpater) {
		this.adapter = adpater;

		removeAllViews();
		if (footerViewAttached)
			addView(footerview);

		notifyChange();

	}

	/**
	 * 设置条目监听事件
	 * 
	 * @param onClickListener
	 */
	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);

	}
}

这样就可以添加footerView了。最终我是使用了这种方案。






  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值