ScrollView中放置ListView

转载 2016年08月31日 15:16:39

最近有个需求是需要在ScrollView中放置一个ListView,如果不做处理的话,直接放置控件会导致:

  1. ListView的高度设置为wrap_content时,每个item的高度无法控制,可能导致item高度为0而不显示。
  2. ListView的高度设置为wrap_content时,疯狂调用getView方法导致卡顿。
  3. ListView的高度设置了合适的高度后,ListView无法滑动。

其对应的解决方法:

  1. 在ListView调用了setAdapter或者notifyDataChange后,使用该方法重新设置ListView的高度。

    public static void setListViewHeightBasedOnChildren(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null)
            return;
    
        int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(), View.MeasureSpec.UNSPECIFIED);
        int totalHeight = 0;
        View view = null;
        for (int i = 0; i < listAdapter.getCount(); i++) {
            //获取每个item的view
            view = listAdapter.getView(i, view, listView);
            if (i == 0)
                view.setLayoutParams(new AbsListView.LayoutParams(desiredWidth, AbsListView.LayoutParams.WRAP_CONTENT));
    
            view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
            //计算总高度
            totalHeight += view.getMeasuredHeight();
        }
        ViewGroup.LayoutParams params = listView.getLayoutParams();
        //加上divider的高度
        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
        listView.requestLayout();
    }
    

    该方法原理就是通过adapter的getView方法返回item的view,计算每个item的高度height乘以item的个数,最后加上divider的高度。(如果知道每个item的高度,可以直接获取adapter的count乘以高度即可,省区调用getView方法的时间)

    使用该方法需要注意:
    1. item的根布局是必须是LinearLayout等重写了`onMeasure`方法的layout,因为获取高度时用到了`view.getMeasuredHeight()`方法.
    2. 该方法会在Adapter的getView方法前被调用。
    
  2. 在ListView外部放置一层单独的FrameLayout(性能最高),设置Layout的高度为wrap_content,然后设置ListView的高度为fill_parent,最后在setAdapternotifyDataChange后修改setListViewHeightBasedOnChildren方法,通过该方法返回带有正确高度的LinearLayout.LayoutParams(你没有看错,用LinearLayout.LayoutParams来设置FrameLayout),以此来设置FrameLayout的高度。这样不会疯狂调用getView方法了。

  3. 在onTouch事件中取消父布局的touch劫持。

    listView.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            v.getParent().requestDisallowInterceptTouchEvent(true);
            return false;
        }
    });
    

如果使用了Github开源项目-PullToRefreshListView,它有一个headView和一个BottomView,所以它计算高度的方法会不同:

public static void setListViewHeightBasedOnChildren(PullToRefreshListView listView) {
    ListAdapter listAdapter = listView.getRefreshableView().getAdapter();
    if (listAdapter == null)
        return;

    int totalHeight = 0;
    View view = null;
    //去掉头尾两个view
    for (int i = 1; i < listAdapter.getCount()-1; i++) {
        view = listAdapter.getView(i, view, listView);
        totalHeight += view.getLayoutParams().height;
    }
    ViewGroup.LayoutParams params = listView.getLayoutParams();
    params.height = totalHeight + (listView.getRefreshableView().getDividerHeight() * (listAdapter.getCount() - 1));
    listView.setLayoutParams(params);
    listView.requestLayout();
}

这里使用的是LayoutParams的height作为item的高度,所以在adapter的getView方法中,应该这样初始化:

public View getView(int position, View convertView, ViewGroup parent) {
    convertView = inflater.inflate(R.layout.parenting_listview_item,parent,false);
}

Android ScrollView和ListView事件冲突问题解决方法

不知道有没有朋友遇到这种问题:就是当你一个ScrollView里面包含一个ListView的时候,你会发现一个问题:当listview里面的item条目过多的时候,在Listview中只会显示一部分,...
  • qq_26888925
  • qq_26888925
  • 2016年07月27日 12:02
  • 470

ScrollView+TabLayout+ViewPager+ListView复杂滑动嵌套、上拉加载

先来看看要实现布局的样式哈,我感觉手动画的更详细嘿嘿。 要实现的就是这样的复杂布局,这里面涉及到各种嵌套滑动的冲突,还涉及ListView的上拉加载,接下来一点点开始哈。一、ScrollView嵌套...
  • hello_1s
  • hello_1s
  • 2016年12月05日 18:32
  • 3618

Android开发之ScrollView中嵌套ListView的解决方案

在工作中,曾多次碰到ScrollView嵌套ListView的问题,网上的解决方法有很多种,但是杂而不全。我试过很多种方法,它们各有利弊。 在这里我将会从使用ScrollView嵌套ListVi...
  • MiniMicall
  • MiniMicall
  • 2014年11月10日 17:10
  • 17936

ScrollView嵌套ListView——解决滑动冲突问题

//布局中的代码实现 一个简单的布局设置 演义滑动冲突
  • Mannver
  • Mannver
  • 2016年04月12日 20:49
  • 11184

android中Scrollview 嵌套ListView显示不完整

本帖最后由 echohe 于 2014-4-9 10:13 编辑 以下文章转自@安卓泡面 在工作中,曾多次碰到ScrollView嵌套ListView的问题,网上的解决方法有很多种,但是杂而不全...
  • loomis13
  • loomis13
  • 2015年08月19日 16:42
  • 3198

ScrollView中嵌套两个ListView

一个ScrollView嵌套两个ListView
  • jia635
  • jia635
  • 2014年11月30日 22:38
  • 1724

Android ScrollView中嵌套ListView,滑动冲突问题的解决

在项目开发过程,遇到ScrollView中嵌套ListView,结果点击ListView上下滑动时,整个页面滑动,也就是滑动事件被ScrollView消费掉了,造成listView无法滑动的结果,然后...
  • androidforwell
  • androidforwell
  • 2016年09月22日 13:01
  • 3240

Android中ListView与ScrollView混合使用

ListView与ScrollView混合使用主要有两种效果: 1、ListView在ScrollView中高度固定。滑动ListView时,ListView滚动。ListView到头或者滑动Scro...
  • c19344881x
  • c19344881x
  • 2015年11月12日 12:58
  • 4561

Android 解决 ListView的item中嵌套ScrollView,ScrollView拦截ListView的Item点击事件的解决办法

前沿:有时候,listview 的item要显示的字段比较多,考虑到显示问题,item外面不得不嵌套ScrollView来实现,于是问题来了,当listview需要做点击事件时,由于ScrollVie...
  • jky_yihuangxing
  • jky_yihuangxing
  • 2016年10月28日 14:36
  • 896

解决scrollview嵌套listview后,listview的setSelection失效问题

项目中scrollview嵌套listview后,各种问题,首先是listview的高度计算问题;后面有liistview的setSelection失效问题 。 前一种网上有多种解决办法,就...
  • blf09
  • blf09
  • 2016年03月22日 21:25
  • 1021
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ScrollView中放置ListView
举报原因:
原因补充:

(最多只允许输入30个字)