NestedScrollView嵌套ListView可行性总结
由于公司项目遗留代码仍然使用PullToRefreshListView(后文简称PTRLV),且存在复用,更换RecyclerView成本太大,同时又想使用CoordinatorLayout来实现一些嵌套滑动效果,所以研究了NestedScrollView嵌套PTRLV的方案。
对于NestedScrollView嵌套普通的ListView,常见的问题有:
- 嵌套后ListView只显示一行。
- ListView无法滑动。
网上的解决方案主要是2种:
重写ListView的onMeasure方法。
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> , MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
将ListView所有子View的高度以及分隔线的高度相加,重新设置给ListView。
private void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter(); //获得Adapter
if (listAdapter == null) {
return;
}
int totalHeight = ;
for (int i = ; i < listAdapter.getCount(); i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(, );
totalHeight += listItem.getMeasuredHeight();
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - ));
listView.setLayoutParams(params);
}
这种方法要求子View的根布局必须是LinearLayout。
这2种方法乍看之下也都能解决NestedScrollView嵌套PTRLV的问题,但其实局限性很大,项目中实践后发现场景稍有变化就仍然有问题。
主要有:
- 有些场景下展示的数据并不会在Activity的onCreate方法中就获取,例如搜索页需要用户输入关键字后才去获取数据,然后才将数据给到PTRLV展示,这时PTRLV只显示半行。
- 在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);
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> , 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事件的。
NestedScrollView嵌套ListView可行性总结的更多相关文章
- NestedScrollView嵌套ListView时只显示一行的解决方法
在使用CoordinatorLayout和AppBarLayout实现嵌套滑动的时候,出现listview没有嵌套滑动: 如果要实现嵌套滑动,则需要添加NestedScrollView,但是结果发现l ...
- NestedScrollView嵌套RecyclerView
天气渐寒,然学习不可懈怠,记录一下使用NestedScrollView嵌套RecyclerView的两个问题,以后遇到可以来这里温故. 应该说在MD中,RecyclerView代替了ListView, ...
- ScrollView嵌套ListView,GridView数据加载不全问题的解决
我们大家都知道ListView,GridView加载数据项,如果数据项过多时,就会显示滚动条.ScrollView组件里面只能包含一个组件,当ScrollView里面嵌套listView,GridVi ...
- 浅谈ScrollView嵌套ListView及ListView嵌套的高度计算
引言 在Android开发中,我们有时会需要使用ScrollView中嵌套ListView的需求.例如:在展示信息的ListView上还有一部分信息展示区域,并且要求这部分信息展示区域在ListVie ...
- 关于ScrollView嵌套ListView问题
Android开发之ScrollView中嵌套ListView的解决方案 原文:http://blog.csdn.net/minimicall/article/details/40983331 ...
- ScrollView 嵌套ListView、RecyclerView(持续更新)
ListView: 只要重写ListView或GridView的onMeasure()方法即可: @Override protected void onMeasure(int widthMeasure ...
- 四种方案解决ScrollView嵌套ListView问题(转)
以下文章转自@安卓泡面 在工作中,曾多次碰到ScrollView嵌套ListView的问题,网上的解决方法有很多种,但是杂而不全.我试过很多种方法,它们各有利弊. 在这里我将会从使用ScrollVie ...
- 解决lScrollView嵌套ListView只显示一行的问题,listvie显示全部的item
ScrollView嵌套ListView只显示一行的问题 1.思路:给listview重新添加一个高度. listview的高度==listview.item的高度之和. 2.注意:关键是添加list ...
- Android之ScrollView嵌套ListView冲突
在ScrollView中嵌套使用ListView,ListView只会显示一行多一点.两者进行嵌套,即会发生冲突.由于ListView本身都继承于ScrollView,一旦在ScrollView中嵌套 ...
随机推荐
- 基于redis ae实现 Linux中的文件系统监控机制(inotify)
(英文部分为转的.代码是个人代码) 1 What's inotify The inotify API provides a mechanism for monitoring file system ...
- mydumper安装及安装故障汇总
mydumper是针对mysql数据库备份的一个轻量级第三方的开源工具,备份方式术语逻辑备份.它支持多线程.备份速度远高于原生态的mysqldump以及众多优异特性. 因此该工具是DBA们的不二选 ...
- mysql实战45讲 (三) 事务隔离:为什么你改了我还看不见 极客时间读书笔记
提到事务,你肯定不陌生,和数据库打交道的时候,我们总是会用到事务.最经典的例子就是转账,你要给朋友小王转100块钱,而此时你的银行卡只有100块钱. 转账过程具体到程序里会有一系列的操作,比如查询余额 ...
- jQuery EasyUI 右键菜单--关闭标签/选项卡
目录结构: noContextMenu.js 文件内容如下: $(function(){ //屏蔽右键菜单 $(document).bind("contextmenu", func ...
- python 时间差计算
import time import datetime datebg=input("date begin:") dateed=input("date end:" ...
- HOJ 1867 经理的烦恼 【 树状数组 】
题意:给出一个区间,求这个区间里面素数的个数 这道题wa了好多次---是因为add操作没有写对 每次更新的时候,应该先判断没有加上y是不是质数,加上了y是不是质数 如果从质数变成不是质数,那么add( ...
- CSS3———linear-gradient() 线性渐变
线性渐变linear-gradient() 遇到了这样的css样式 body { height: 100%; background-color: #ffffff; background-image: ...
- 优动漫PAINT-凌霄花画法
再见小清新~这次教程教授的是凌霄花的画法!话说这个作者的花卉系列都很米粒啊~配色什么的,赞到没话说~ 教程是简单,呃.... 没有优动漫PAINT软件肿么办? 别着急,╭(╯^╰)╮ 小编给你送来了 ...
- 路飞学城Python-Day7
Moudle 2 1.鸡汤中国人均阅读4.35本:日本40本:韩国17本:法国20本:以色列60本成长的路上需要读书,坚持读书内心会得到升华的想法不要太多,尽量多读书,多充电多读书,多看报,少吃零食, ...
- BZOJ 2560(子集DP+容斥原理)
2560: 串珠子 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 757 Solved: 497[Submit][Status][Discuss] ...