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

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

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

java代码 [![](http://www.eyeandroid.com/source/plugin/milu_hightLight/help.png)](http://www.eyeandroid.com/)
- <span class="comment">/**</span>

- <span class="comment">* 动态设置listView的高度</span>

- <span class="comment">* count 总条目</span>

- <span class="comment">*/</span>

- <span class="keyword">private</span> <span class="keyword">void</span> setListViewHeight(ListView listView, BaseAdapter adapter,

- <span class="keyword">int</span> count) {

- <span class="keyword">int</span> totalHeight = <span class="number"></span>;

- <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number"></span>; i < count; i++) {

- View listItem = adapter.getView(i, <span class="keyword">null</span>, listView);

- listItem.measure(<span class="number"></span>, <span class="number"></span>);

- totalHeight += listItem.getMeasuredHeight();

- }

- 
- ViewGroup.LayoutParams params = listView.getLayoutParams();

- params.height = totalHeight + (listView.getDividerHeight() * count);

- listView.setLayoutParams(params);

- }

这样做的前提条件是布局文件中ListView的高度要指定,这样才能重新计算,不要设成wapcontent!

二.不全部展示数据,二者皆可滑动。

此方法不用重新计算ListView的高度,只需焦点在Listview上的时候,ScrollView能把滑动权主动交给Listview,这样需要重写ScrollView的一个方法,如下:

java代码 [![](http://www.eyeandroid.com/source/plugin/milu_hightLight/help.png)](http://www.eyeandroid.com/)
- <span class="annotation">@Override</span>

- <span class="keyword">public</span> <span class="keyword">boolean</span> onInterceptTouchEvent(MotionEvent ev) {

- <span class="keyword">return</span> <span class="keyword">false</span>;

- }

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

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

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

java代码 [![](http://www.eyeandroid.com/source/plugin/milu_hightLight/help.png)](http://www.eyeandroid.com/)
- <span class="comment">/**</span>

- <span class="comment">* 设置不滚动</span>

- <span class="comment">*/</span>

- <span class="keyword">public</span> <span class="keyword">void</span> onMeasure(<span class="keyword">int</span> widthMeasureSpec, <span class="keyword">int</span> heightMeasureSpec)

- {

- <span class="keyword">int</span> expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> <span class="number">2</span>,

- MeasureSpec.AT_MOST);

- <span class="keyword">super</span>.onMeasure(widthMeasureSpec, expandSpec);

- 
- }

这种方法是同事告诉我的,我没有用过。

做到这里,ScrollView和ListView的问题是解决了,但是ListView的效率问题出现了。

你会发现在ListView的adapter里的getview方法重复执行了很多次,技术使用了缓存技术也是无用的。

有时候数据只有两三个,但是getView方法却被执行了40多次。这样肯定是不行的。但是为什么单独使用ListView的时候却不会出现这种问题呢?

这个原因肯定出在ScrollView和ListView共存上。Google了一下,外国人都不建议他们共存,但是需求是这样的怎么办呢?

我的最终解决方案:自己写一个类似ListView的东西

一. 最初:

java代码 [![](http://www.eyeandroid.com/source/plugin/milu_hightLight/help.png)](http://www.eyeandroid.com/)
- <span class="comment">/**</span>

- <span class="comment">* 虚拟listview</span>

- <span class="comment">*</span>

- <span class="comment">* @author JustMe</span>

- <span class="comment">*</span>

- <span class="comment">*/</span>

- <span class="keyword">public</span> <span class="keyword">class</span> MyListView <span class="keyword">extends</span> LinearLayout {

- 
- <span class="keyword">private</span> BaseAdapter adapter;

- <span class="keyword">private</span> MyOnItemClickListener onItemClickListener;

- 
- <span class="comment">/**</span>

- <span class="comment">* 通知更新listview</span>

- <span class="comment">*/</span>

- <span class="keyword">public</span> <span class="keyword">void</span> notifyChange() {

- <span class="keyword">int</span> count = getChildCount();

- LayoutParams params = <span class="keyword">new</span> LayoutParams(LayoutParams.FILL_PARENT,

- LayoutParams.WRAP_CONTENT);

- <span class="keyword">for</span> (<span class="keyword">int</span> i = count; i < adapter.getCount(); i++) {

- <span class="keyword">final</span> <span class="keyword">int</span> index = i;

- <span class="keyword">final</span> LinearLayout layout = <span class="keyword">new</span> LinearLayout(getContext());

- layout.setLayoutParams(params);

- layout.setOrientation(VERTICAL);

- View v = adapter.getView(i, <span class="keyword">null</span>, <span class="keyword">null</span>);

- v.setOnClickListener(<span class="keyword">new</span> OnClickListener() {

- 
- <span class="annotation">@Override</span>

- <span class="keyword">public</span> <span class="keyword">void</span> onClick(View v) {

- <span class="keyword">if</span> (onItemClickListener != <span class="keyword">null</span>) {

- onItemClickListener.onItemClick(MyListView.<span class="keyword">this</span>,

- layout, index, adapter.getItem(index));

- }

- }

- });

- <span class="comment">// 每个条目下面的线</span>

- ImageView imageView = <span class="keyword">new</span> ImageView(getContext());

- imageView.setBackgroundResource(R.drawable.divider_list);

- imageView.setLayoutParams(params);

- layout.addView(v);

- layout.addView(imageView);

- addView(layout, index);

- }

- }

- 
- <span class="keyword">public</span> MyListView(Context context) {

- <span class="keyword">super</span>(context);

- initAttr(<span class="keyword">null</span>);

- }

- 
- <span class="keyword">public</span> MyListView(Context context, AttributeSet attrs) {

- <span class="keyword">super</span>(context, attrs);

- initAttr(attrs);

- }

- 
- <span class="comment">/**</span>

- <span class="comment">* 设置方向</span>

- <span class="comment">*</span>

- <span class="comment">* @param attrs</span>

- <span class="comment">*/</span>

- <span class="keyword">public</span> <span class="keyword">void</span> initAttr(AttributeSet attrs) {

- setOrientation(VERTICAL);

- }

- 
- 
- 
- 
- <span class="keyword">public</span> BaseAdapter getAdapter() {

- <span class="keyword">return</span> adapter;

- }

- 
- <span class="comment">/**</span>

- <span class="comment">* 设置adapter并模拟listview添加数据</span>

- <span class="comment">*</span>

- <span class="comment">* @param adpater</span>

- <span class="comment">*/</span>

- <span class="keyword">public</span> <span class="keyword">void</span> setAdapter(BaseAdapter adpater) {

- <span class="keyword">this</span>.adapter = adpater;

- 
- 
- notifyChange();

- 
- }

- 
- <span class="comment">/**</span>

- <span class="comment">* 设置条目监听事件</span>

- <span class="comment">*</span>

- <span class="comment">* @param onClickListener</span>

- <span class="comment">*/</span>

- <span class="keyword">public</span> <span class="keyword">void</span> setOnItemClickListener(MyOnItemClickListener onClickListener) {

- <span class="keyword">this</span>.onItemClickListener = onClickListener;

- }

- 
- 
- 
- <span class="comment">/**</span>

- <span class="comment">* 点击事件监听</span>

- <span class="comment">*</span>

- <span class="comment">* @author JustMe</span>

- <span class="comment">*</span>

- <span class="comment">*/</span>

- <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">interface</span> MyOnItemClickListener {

- <span class="keyword">public</span> <span class="keyword">void</span> onItemClick(ViewGroup parent, View view, <span class="keyword">int</span> position,

- Object o);

- 
- }

- }

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

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

二. 升级:

java代码 [![](http://www.eyeandroid.com/source/plugin/milu_hightLight/help.png)](http://www.eyeandroid.com/)
- <span class="keyword">public</span> <span class="keyword">class</span> MyListView <span class="keyword">extends</span> LinearLayout{

- <span class="keyword">private</span> BaseAdapter adapter;

- <span class="keyword">private</span> MyOnItemClickListener onItemClickListener;

- <span class="keyword">boolean</span> footerViewAttached = <span class="keyword">false</span>;

- <span class="keyword">private</span> View footerview;

- 
- <span class="comment">/**</span>

- <span class="comment">* 通知更新listview</span>

- <span class="comment">*/</span>

- <span class="keyword">public</span> <span class="keyword">void</span> notifyChange() {

- <span class="keyword">int</span> count = getChildCount();

- <span class="keyword">if</span> (footerViewAttached) {

- count&#8211;;

- }

- LayoutParams params = <span class="keyword">new</span> LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);

- <span class="keyword">for</span> (<span class="keyword">int</span> i = count; i < adapter.getCount(); i++) {

- <span class="keyword">final</span> <span class="keyword">int</span> index = i;

- <span class="keyword">final</span> LinearLayout layout = <span class="keyword">new</span> LinearLayout(getContext());

- layout.setLayoutParams(params);

- layout.setOrientation(VERTICAL);

- View v = adapter.getView(i, <span class="keyword">null</span>, <span class="keyword">null</span>);

- v.setOnClickListener(<span class="keyword">new</span> OnClickListener() {

- 
- <span class="annotation">@Override</span>

- <span class="keyword">public</span> <span class="keyword">void</span> onClick(View v) {

- <span class="keyword">if</span> (onItemClickListener != <span class="keyword">null</span>) {

- onItemClickListener.onItemClick(MyListView.<span class="keyword">this</span>, layout, index,

- adapter.getItem(index));

- }

- }

- });

- ImageView imageView = <span class="keyword">new</span> ImageView(getContext());

- imageView.setBackgroundResource(R.drawable.divider_list);

- imageView.setLayoutParams(params);

- layout.addView(v);

- layout.addView(imageView);

- addView(layout, index);

- }

- }

- 
- <span class="keyword">public</span> MyListView(Context context) {

- <span class="keyword">super</span>(context);

- initAttr(<span class="keyword">null</span>);

- }

- 
- <span class="keyword">public</span> MyListView(Context context, AttributeSet attrs) {

- <span class="keyword">super</span>(context, attrs);

- initAttr(attrs);

- }

- 
- <span class="keyword">public</span> <span class="keyword">void</span> initAttr(AttributeSet attrs) {

- 
- setOrientation(VERTICAL);

- }

- 
- <span class="comment">/**</span>

- <span class="comment">* 初始化footerview</span>

- <span class="comment">*</span>

- <span class="comment">* @param footerView</span>

- <span class="comment">*/</span>

- <span class="keyword">public</span> <span class="keyword">void</span> initFooterView(<span class="keyword">final</span> View footerView) {

- <span class="keyword">this</span>.footerview = footerView;

- }

- 
- <span class="comment">/**</span>

- <span class="comment">* 设置footerView监听事件</span>

- <span class="comment">*</span>

- <span class="comment">* @param onClickListener</span>

- <span class="comment">*/</span>

- <span class="keyword">public</span> <span class="keyword">void</span> setFooterViewListener(OnClickListener onClickListener) {

- <span class="keyword">this</span>.footerview.setOnClickListener(onClickListener);

- }

- 
- <span class="keyword">public</span> BaseAdapter getAdapter() {

- <span class="keyword">return</span> adapter;

- }

- 
- <span class="comment">/**</span>

- <span class="comment">* 设置adapter并模拟listview添加????数据</span>

- <span class="comment">*</span>

- <span class="comment">* @param adpater</span>

- <span class="comment">*/</span>

- <span class="keyword">public</span> <span class="keyword">void</span> setAdapter(BaseAdapter adpater) {

- <span class="keyword">this</span>.adapter = adpater;

- 
- removeAllViews();

- <span class="keyword">if</span> (footerViewAttached)

- addView(footerview);

- 
- notifyChange();

- 
- }

- 
- <span class="comment">/**</span>

- <span class="comment">* 设置条目监听事件</span>

- <span class="comment">*</span>

- <span class="comment">* @param onClickListener</span>

- <span class="comment">*/</span>

- <span class="keyword">public</span> <span class="keyword">void</span> setOnItemClickListener(MyOnItemClickListener onClickListener) {

- <span class="keyword">this</span>.onItemClickListener = onClickListener;

- }

- 
- <span class="comment">/**</span>

- <span class="comment">* 没有下一页了</span>

- <span class="comment">*/</span>

- <span class="keyword">public</span> <span class="keyword">void</span> noMorePages() {

- <span class="keyword">if</span> (footerview != <span class="keyword">null</span> && footerViewAttached) {

- removeView(footerview);

- footerViewAttached = <span class="keyword">false</span>;

- }

- }

- 
- <span class="comment">/**</span>

- <span class="comment">* 可能还有下一??</span>

- <span class="comment">*/</span>

- <span class="keyword">public</span> <span class="keyword">void</span> mayHaveMorePages() {

- <span class="keyword">if</span> (!footerViewAttached && footerview != <span class="keyword">null</span>) {

- addView(footerview);

- footerViewAttached = <span class="keyword">true</span>;

- }

- }

- 
- <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">interface</span> MyOnItemClickListener {

- <span class="keyword">public</span> <span class="keyword">void</span> onItemClick(ViewGroup parent, View view, <span class="keyword">int</span> position, Object o);

- 
- }

- }

 

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