用PullToRefresh的开源包包时,遇到了这样一个问题。我将ListView放进ScrollView里面,发现ListView无论如何,只会显示一行。

  在查阅的各种文档和资料后,发现在ScrollView中嵌套ListView空间,无法正确的计算ListView的大小。ListView本身有多少项,ScrollView并不知道,也不会理它,只把它当作一个小项来处理了,下面的空间还要留给别的东西呢。

  怎么办呢?为此,我们需要禁止ListView本身的滚动,将组件的高度给算出来。很多地方给出的方法是,在项目中去计算ListView的高度,我觉得这样是不科学的。于是,我采用自定义一个ListView,并教给它算自己高度的新方法就好了。

public class InScrollListView extends ListView {
    public InScrollListView(Context context) {
        super(context);
    }

    public InScrollListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public InScrollListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public InScrollListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
    }
}

  这样,把之前的ListView替换成这个新的ListView就没问题啦。

====================这个方法是错的!!!!!!!!====================

当年天真的我使用了这个方法。后果真是不堪设想啊!!!让我们冷静一下,首先我们来思考一下这个原理。

1.为什么Listview放入Scrollview中会失效。

Listview和Scrollview与常规的view不同。常规的view只有一个height,内容有多少,这个height就会有多高。而Listview和Scrollview有两个height,一个scrollHeight一个viewHeight。试想一下,当我们把一个Listview放进一个Scrollview。Listview只会以它的viewHeight显示出来,又因为与Scrollview同方向可滑动,从而失去了滑动能力,所以Listview只显示一项,又不能滑动。

 

2.我们需要什么样的效果

我们希望的效果是,Listview在Scrollview中能够完全的展示,即scrollHeight与viewHeight相等。

 

3.上面的方法有什么问题

上面的方法修改了Listview中的onMeasure方法,将Listview的height设置为atMost模式,这样Listview的显示高度就与滑动高度相等了,看起来解决了问题。

但是,这个方法有个陷阱。由于listview完全展示了,那么listview在初始化时,就会为每一个item执行getView。这是一个非常恐怖的操作。因为通常来说,Listview是不会限定item数量的。此外,由于所有的item都在显示高度内,item也不会被回收复用。这样,如果listview的item数量较大时,这个操作将非常耗时,导致掉桢,卡UI,甚至未响应。

 

4.解决办法

不得不遗憾地说,目前,我没有找到优雅的解决办法,如果这篇博文能有幸被哪位大大看见,还请大大不吝赐教。

目前,我所知的解决方法是,在有无限项item时,不要使用ScrollView。不管情况有多复杂,只使用ListView(当然RecyclerView也可以)。不管怎样的情况,都通过headerView,footerView和不同的itemType去解决(RecyclerView只有itemType一种途径)。这样我们需要写一个非常复杂的Adapter,但现在我所知道的,也只有这样。

 

posted on 2015-03-18 15:27  Fishbonell  阅读(423)  评论(0编辑  收藏  举报