由于公司项目遗留代码仍然使用PullToRefreshListView(后文简称PTRLV),且存在复用,更换RecyclerView成本太大,同时又想使用CoordinatorLayout来实现一些嵌套滑动效果,所以研究了NestedScrollView嵌套PTRLV的方案。

对于NestedScrollView嵌套普通的ListView,常见的问题有:

  1. 嵌套后ListView只显示一行。
  2. ListView无法滑动。

网上的解决方案主要是2种:

  1. 重写ListView的onMeasure方法。

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

将ListView所有子View的高度以及分隔线的高度相加,重新设置给ListView。

private void setListViewHeightBasedOnChildren(ListView listView) {ListAdapter listAdapter = listView.getAdapter(); //获得Adapterif (listAdapter == null) { return;}int totalHeight = 0;for (int i = 0; i < listAdapter.getCount(); i++) {View listItem = listAdapter.getView(i, null, listView);listItem.measure(0, 0);totalHeight += listItem.getMeasuredHeight();}ViewGroup.LayoutParams params = listView.getLayoutParams();params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));listView.setLayoutParams(params);}

  1. 这种方法要求子View的根布局必须是LinearLayout。

这2种方法乍看之下也都能解决NestedScrollView嵌套PTRLV的问题,但其实局限性很大,项目中实践后发现场景稍有变化就仍然有问题。

主要有:

  1. 有些场景下展示的数据并不会在Activity的onCreate方法中就获取,例如搜索页需要用户输入关键字后才去获取数据,然后才将数据给到PTRLV展示,这时PTRLV只显示半行。
  2. 在PTRLV中改写添加的预加载功能失效。

第1个问题出现的原因在于,上述2种解决方案都是改变PTRLV中真正的ListView的大小,让它能够将全部的子View展现出来。在这个场景中,界面初始化时,ListView中是没有数据的,所以在measure时ListView本身大小为0,只测量出了PTRLV的那个滑动指示块的高度,所以PTRLV只有那么高。

那为什么获取到数据后再notify还是只有这么高呢?因为PTRLV在真正的ListView之外还有两层FrameLayout。虽然ListView因为重写了onMeasure方法已经展示全了,但这两层FrameLayout还是只有滑块那么高,所以PTRLV看起来还是没有改变。

解决方案为:
重写PTRLV内部的FrameLayout的onMeasure方法,跟ListView一样就行

public class NoScrollFrameLayout extends FrameLayout {public NoScrollFrameLayout(Context context) {super(context);}public NoScrollFrameLayout(Context context, AttributeSet attrs) {super(context, attrs);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);super.onMeasure(widthMeasureSpec, expandSpec);}
}

在PTRLV的父类PullToRefreshBase中改写addRefreshableView方法

private void addRefreshableView(Context context, T refreshableView) {mRefreshableViewWrapper = new NoScrollFrameLayout(context);mRefreshableViewWrapper.addView(refreshableView, ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT);addViewInternal(mRefreshableViewWrapper, new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT));
}

第2个问题出现的原因是因为滑动事件的冲突。这里可能会有疑问,为什么还说滑动事件有冲突,通过上述方案不是已经可以正常滑动了吗?那是因为那只是看上去像ListView的滑动,其实是NestedSrcollView在滑动,ListView根本没有动。

从第1个问题的原因中我们已经知道了,解决NestedScrollView中嵌套ListView显示不全问题的方法,其本质都是手动修改ListView的内容的高度,而且不是将高度match_parent,而是将ListView的子View全部加载进来,假如有50个数据,就一次性加载50个子View,所以ListView就相当于一个有50个子View的LinearLayout。(当然也就不会有复用,性能很差)

另一方面,NestedSrcollView在onInterceptTouchEvent中拦截了所有的Touch事件,ListView没有分发到任何事件,所以虽然看上去像ListView在滑动,实际上是ScrollView包裹着相当于LinearLayout的ListView在滑动,而由于我们项目的预加载逻辑写在ListView的onScrollStateChange方法中,没有分到任何Touch事件的情况下根本不会调用onScrollStateChange,因此预加载就失效了。

这个问题在不改动预加载逻辑实现位置的情况下是无解的。同时也可以得出:如果你在ListView的Touch事件中有自定义的逻辑,那么请不要用NestedSrcollView嵌套ListView,因为NestedSrcollView会拦截Touch事件,所有的滑动解决方案并没有真正解决滑动冲突,ListView是获取不到Touch事件的。

转载于:https://www.cnblogs.com/zhujiabin/p/7371735.html

NestedScrollView嵌套ListView可行性总结相关推荐

  1. Android中RecyclerView嵌套RecyclerView或嵌套ListView

    Android中RecyclerView嵌套RecyclerView或嵌套ListView

  2. scrollview中嵌套listview产生冲突问题

    在scrollview中嵌套listview或者gridview时 如果listview或者gridview的高度时wrap-content会导致两者只显示一行多一点 原因: listview和gri ...

  3. Android之解决在scrollview中嵌套ListView切换界面时scrollview整体向下滑动

    有时候我们在scrollview中会嵌套ListView,在嵌套ListView(ListView上面还有一些控件)后,切换Activity时会发现整个 scrollview 被向下滑动直到ListV ...

  4. 当PullToRefreshScrollView里面嵌套ListView

    当PullToRefreshScrollView里面嵌套ListView,ListView上面还是有内容的,当下拉刷新的 时候,数据填充完成之后ListView就会往上面滑动,导致ListView上面 ...

  5. 四种方案解决ScrollView嵌套ListView问题

    在工作中,曾多次碰到ScrollView嵌套ListView的问题,网上的解决方法有很多种,但是杂而不全.我试过很多种方法,它们各有利弊. 在这里我将会从使用ScrollView嵌套ListView结 ...

  6. ScrollView中嵌套ListView

    放置比较少的ListView组件效果图:                         Item布局文件  list_view_item.xml  布局文件的内容: <RelativeLayo ...

  7. android中ScrollView嵌套ListView或GridView显示位置问题

    Android中ScrollView中嵌套ListView或GridView时在开始进入界面时总是显示中间位置,开头的位置显示不出来.这种情况下只需要在ScrollView的父控件中添加以下两行代码即 ...

  8. ScrollView嵌套ListView后,进入页面不从顶部开始显示的问题解决

    ScrollView嵌套ListView后,进入页面不从顶部开始显示的问题解决 首先,正常情况下,如果在ScrollView里嵌套ListView后,会发现ListView只显示1条数据 那么,为了解 ...

  9. Android之解决NestedScrollView嵌套RecyclerView部分手机返回到这个页面Recyclerview顶部,而不是页面NestedScrollView顶部

    1.问题 NestedScrollView嵌套Recyclerview部分手机返回到这个页面Recyclerview顶部,而不是页面NestedScrollView顶部 部分布局大致如下 <an ...

  10. 解决Android学习之ScollView嵌套ListView和GridView问题

    Android学习之ScollView嵌套ListView和GridView问题,gridview与这种写法一样 import android.content.Context; import andr ...

最新文章

  1. Vue 动态路由的实现以及 Springsecurity 按钮级别的权限控制
  2. MySQL列转行sql语句
  3. ACL 2021 | 复旦大学邱锡鹏组:面向不同NER子任务的统一生成框架
  4. [zz]Ubuntu下使用Eclipse和PyDev搭建完美Python开发环境
  5. 组件化与插件化的差别在哪里?内含福利
  6. hal库串口dma卡死_HAL库版DMA循环模式串口数据收发
  7. 排序算法python实现_合并排序算法– Java,C和Python实现
  8. 第一行代码笔记-第五章
  9. VS报错——无法打开文件XXX.lib
  10. 《数据结构》-二叉树(二叉链表实现)
  11. java论文3000字_一篇文章让你真正了解Java(纯干货)
  12. 【智能优化算法-灰狼算法】基于非支配排序灰狼优化器(NS-GWO)算法求解多目标优化算法附matlab代码
  13. 认识计算机微课导学单,微课“任务单”与“导学案”之比较
  14. CentOS7创建组删除组创建用户删除用户
  15. 关于双因素认证(2FA),这些基础知识你一定要知道
  16. 从user 登陆开始
  17. RFID技术如何解决鞋帽行业应用
  18. 宜信 、《麻省理工科技评论》共同揭晓: 35岁以前最有可能改变世界的中国科技精英丨Xtecher 前线
  19. Mac 下eclipse 快捷键
  20. 授权sh文件执行权限

热门文章

  1. 微服务在微信的架构实践
  2. 微信类APP如何架构才能省流量
  3. Linux Shell 流程控制语句实例
  4. mysql基础之查询缓存、存储引擎
  5. Linux文件夹操作
  6. springboot + mybatis + 多数据源
  7. 云中树莓派(3):通过 AWS IoT 控制树莓派上的 Led
  8. python产生随机值-random模块
  9. 仿复制粘贴功能,长按弹出tips的实现
  10. 服务器端 viewstate