Android ScrollView 嵌套ListView与GridView的最终解决方案

前言:(由于时间紧,这里只提供思路,和简单代码片段,如果是纯拿来主义,什么都不看就直接用,本文章是满足不了的)项目中难免会遇到ScrollView与ListView等控件的嵌套,而这些控件的嵌套会出现许多意想不到的问题。(以ListView为例)
问题一:我的ListView怎么只有一行?
问题二:当出现较复杂的页面的时候刷新适配器,如果你打印下log,你会震惊的发现,怎么会这样,怎么会这么卡。
如果项目里不需要获取到滑动高度,并且只有一个ListView,那么只需要把除ListView之外的布局单独抽出来,通过添加头(底)布局的方式实现。
如果项目里并不需要大量的刷新操作,并且数据源就那几个(特别是我们做有那种规格的GridView的时候),个人建议是使用重写过OnMeasure()的ListView(GridView),重写方法代码都一样,如下:

public class AllListView extends ListView {
    public AllListView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public AllListView(Context context) {
        super(context);
    }

    public AllListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, expandSpec);
    }
}

这种方式简单,粗暴直接。如遇到LinearLayout嵌套的问题,ListView和GridView只显示一行,那么用这个ListView就可以解决问题。

那么接下来,如果你的项目要做的细致,你会发现在一些大的页面是需要获取到滑动高度的,这也是比较让人纠结的。为了解决问题,你选择了ScrollView嵌套ListView。这确实也是一种实现方法。但随之而来的,当你刷新适配器的时候,你会发现怎么这么卡?(笔者是与pulllToRefreshScrollView嵌套出现的卡顿),这种用户体验是不能忍受的。于是才有了这篇博文。

笔者的上一个项目是要做标题栏颜色透明度渐变的,于是就有了以上的实现方式,ScrollView嵌套ListView。看似除了这种实现方式以为,再没有别的实现方式了。其实不然,今天,笔者用了将近一天的时间去测试别的方式,找到了以下比较好的实现方式。

情景一:你的headerView高度是肯定比你所需求的高度高,并且高的很明显 ,比如,你要获取的高度变化值是在0~255 ,你的headerView的高度是400。那么这种情况下也是大多数情况,使用以下解决方案获取高度值:

public int getMeasureScrollY(){
        int length=100;
        if (getChildCount()==0) {
            return 0;
        }
        if (getFirstVisiblePosition()==0) {
            length=getChildAt(0).getTop();
        }
        Log.i("listview", "==="+length);
        return length;
    }

此种方式,当然这只是一个测试方法,length默认值是100就是你所需要的获取的滑动距离最大值。我知道这种写法很不好,各位同仁去想怎么处理这个返回值的问题,或者项目里再做修改,相信会有很多方式去处理。

还有一种,个人感觉应该是很少见,所需的滑动距离超过headerView了。(目前所能想到的只有置顶功能了)这种效果的实现可以通过ListView的滑动监听来实现,比如 第10个条目可见,就显示置顶图标。
至于获取滑动高度可以通过监听器的方式实现,以下是代码:


/**
*重写onScrollChanged方法
*/
    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        // TODO Auto-generated method stub
        super.onScrollChanged(l, t, oldl, oldt);

        if (onMyListViewScrollListener!=null) {
            onMyListViewScrollListener.onMeasureFirst(getMeasureFirstVisibleScrollY());
        }
    }

    public int getMeasureFirstVisibleScrollY(){
        int length=100;
        if (getChildCount()==0) {
            return 0;
        }

        if (getFirstVisiblePosition()==0) {
            length=getChildAt(0).getTop();
        }
        Log.i("listview", "==="+length);
        return length;  
    }

    public interface onMyListViewScrollListener{
        void onMeasureFirst(int scrollY);
    }
    private onMyListViewScrollListener onMyListViewScrollListener;
    public onMyListViewScrollListener getOnMyListViewScrollListener() {
        return onMyListViewScrollListener;
    }
    public void setOnMyListViewScrollListener(onMyListViewScrollListener onMyListViewScrollListener) {
        this.onMyListViewScrollListener = onMyListViewScrollListener;
    }

其实说了这么多 就一个思想,不要使用ScrollView嵌套ListView以及GridView.如果大家还有碰到什么问题,欢迎留言,大家一起进步。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值