NestedScrollView嵌套viewpager不显示内容的解决方案
创始人
2024-06-03 00:55:50
0

一、概念分析

NestedScrollView里面只能有一个ViewGroup,也就是只允许有一个子节点(允许一个父子节点包含多个子子节点)的存在。
  1. 如果你的NestedScrollView包含了多个子节点就会报错,一般来说,都会在所有子节点的最外层嵌套一个LinearLayout或者其他你业务场景的布局。

子节点:通俗的讲,一个button是一个子节点,一个TextView也是一个子节点,以此类推,每个控件都可以理解为一个子节点

  1. viewpager为什么不能显示内容,无论你是这样设置宽高

android:layout_width="match_parent"
android:layout_height="wrap_content"

还是这样设置宽高,都无法显示

android:layout_width="match_parent"
android:layout_height="match_parent"

但是你给高度设置具体的数值时“android:layout_height=“xxxdp””,才可以显示内容,但是如果你的ViewPager里面的Fragment 拥有一个RecyclerView的时候,固定的数值明显不能从根本上解决问题。

原因:

NestedScrollView 计算高度先于 ViewPager 渲染呈现前,所以 ViewPager 的高度才会一直是0,除非你自己给了固定高度

问题解决方案一:

在NestedScrollView 控件属性中加入
android:fillViewport=“true”

局限是:低于Android 9 以下版本开发的时候

问题解决方案二:

给ViewPager 重写一遍测量,重新给测量高度;
在每次测完后将测量得到的高度保存下来,
下次ViewPager 再切换回来就可以直接设置高度

步骤一:创建自定义的 AutoHeightViewPager 类,继承ViewPager 覆盖重写 计算高度 的onMeasure 方法,并梳理计算和保存原先的高度值等等…

public class AutoHeightViewPager extends ViewPager {private int mHeight = 0;/** 已经获取到的高度下标 : 当前的高度 */private int mCurPosition = 0;/** 当前显示下标 */private int mPosition = 0;/** 按下标存储View历史高度 */private HashMap mChildrenViews = new LinkedHashMap();/** 记录页面是否存储了高度 */private HashMap indexList = new LinkedHashMap();/** 做自适应高度,必须先进行初始化标记 */public void initIndexList(int size) {mHeight = 0;mCurPosition = 0;mPosition = 0;for (int i = 0; i < size; i++) {/** 初始化高度存储状态 */indexList.put(i, false);}}public AutoHeightViewPager(@NonNull Context context) {super(context);}public AutoHeightViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {super(context, attrs);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int height = 0;if (indexList.size() > 0) {if (indexList.get(mPosition)) {height = mChildrenViews.get(mPosition);} else {for (int i = 0; i < getChildCount(); i++) {View child = getChildAt(i);child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));int h = child.getMeasuredHeight();if (h > height) {height = h;}}mHeight = height;}}heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);super.onMeasure(widthMeasureSpec, heightMeasureSpec);}/*** 在viewpager 切换的时候进行更新高度*/public void updateHeight(int current) {this.mPosition = current;if (indexList.size() > 0) {saveIndexData();if (indexList.get(current)) {int height = 0;if (mChildrenViews.get(current) != null) {height = mChildrenViews.get(current);}LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams();if (layoutParams == null) {layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, height);} else {layoutParams.height = height;}setLayoutParams(layoutParams);}this.mCurPosition = current;}}/*** 保存已经测绘好的高度*/private void saveIndexData() {if (!indexList.get(mCurPosition)) {/** 没保存高度时,保存 */indexList.put(mCurPosition, true);mChildrenViews.put(mCurPosition, mHeight);}}
}

步骤二:在xml中引用自定义的控件

 xxx.xxx.xxx是你的自定义控件路径,也就是你AutoHeightViewPager在哪个包下的路径

注意:AutoHeightViewPager类中一定要有

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

不然会报

Android.View.InflateException: Binary XML File Line #异常

步骤三:在你的Activity / Fragment 中引用

         /** 初始化记录是否保存高度的下标 , 注:在重新刷新加载页面的时候,需要对下标进行重新初始化 */viewpager.initIndexList(fragments.size());/** 添加viewpager 切换监听 */viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {@Overridepublic void onPageScrolled(int i, float v, int i1) {}@Overridepublic void onPageSelected(int i) {//在每次切换的时候更新高度viewpager.updateHeight(i);}@Overridepublic void onPageScrollStateChanged(int i) {}});fragments.size() 代表你fragments的数量大小,也可以传入具体的int数值

二、所遇问题

遇到了一个问题: 滑动的时候两边的 Fragment 会跟随 , 就是左边的 Fragment 滑动到一定高度(右边的 Fragment 是不滑动的) , 切换到右边的 Fragment ,发现高度跟左边的 Fragment 滑动的高度一样了 , 反正滑动左右两边的 Fragment , 另一边的都会跟随滑动到一样的高度

分析

下面我们来简单分析下,虽然这个现象很奇怪,但是如果你接触ViewPager较多的话,那么你肯定知道ViewPager是有缓存机制的,也就是默认会预加载左右各一个页面,而我们的demo中,很显然,初次进入的时候,加载第一个页面,同时第二个标签页对应的页面也是会加载的(预加载),而我们的第三个页面却没有预加载,这时候切换,可能导致view还没有加载就直接测量其高度,这时候自然是测量不到的,所以我们可以通过设置初次加载的时候预加载所有的页面来解决这个问题,虽然不优雅。

解决方案

所以我们在代码中只需要给ViewPager加上如下一行代码

viewPager.setOffscreenPageLimit(titleList.size());

相关内容

热门资讯

石家庄驼梁景区导游词 石家庄驼梁景区导游词尊敬的各位游客:  大家好!  欢迎大家来到驼梁,我是中游旅行社的一名导游员,我...
介绍傣家竹楼导游词300 傣家竹楼是傣族固有的典型建筑。下层高约七八尺,四无遮栏,牛马拴束于柱上。上层近梯处有一露台,转进为长...
电视剧《乱世佳人》简介及经典... 电视剧《乱世佳人》简介及经典台词  电视剧简介:  《乱世佳人》亦可称为民国版《美人心计》,由唐嫣饰...
丹东鸭绿江导游词 丹东鸭绿江导游词  鸭绿江是我们中国和朝鲜的分界线,各位导游,请看下面的丹东鸭绿江导游词,希望可以帮...
幼儿园运动会闭幕式主持词 幼儿园运动会闭幕式主持词  主持人在台上表演的灵魂就表现在主持词中。随着社会一步步向前发展,各种场合...
70大寿主持词 70大寿主持词  主持词的写作需要将主题贯穿于所有节目之中。现今社会在不断向前发展,主持人的需求越来...
个人领奖感谢词 个人领奖感谢词(精选7篇)  获得奖励或者嘉奖,不仅是一份荣誉,更是一份激励。你知道怎么写感谢词吗,...
重阳节经典致辞 关于重阳节经典致辞(精选6篇)  在生活、工作和学习中,大家都不可避免地会接触到致辞吧,致辞要求风格...
幼儿园元旦文艺汇演主持词 男小主持:尊敬的家长,亲爱的老师女小主持:可爱的小朋友合:大家新年好!男小主持:春夏秋冬,黑夜清晨女...
大话西游降妖篇2台词 大话西游降妖篇2台词  导语:《西游伏妖篇》也是继春节档周星驰执导电影《美人鱼》中徐克客串表演之后,...
晚会活动主持词   引导语:晚会最重要的一点就是主持,而有关晚会活动的主持词要怎么写呢?接下来是小编为你带来收集整理...
周年庆活动主持词 周年庆活动主持词9篇  借鉴诗词和散文诗是主持词的一种写作手法。在人们越来越多的参与各种活动的今天,...
《手机》经典台词 《手机》经典台词  砖头媳妇:装得跟头会想事的猪一样。  于文娟:老费吃了不管用,说明他不是不能,而...
公司工会代表大会主持词 公司工会代表大会主持词  各位代表:  请大家坐好,会议马上就要开始了,公司工会代表大会主持词。(待...
影视剧里那些讲完就领便当的台... 关于影视剧里那些讲完就领便当的台词  无论是什么类型的影视作品,片中的角色在将死之前大都会变得不太一...
高三毕业典礼主持词 高三毕业典礼主持词15篇  主持词的写作需要将主题贯穿于所有节目之中。在如今这个时代,活动集会越来越...
班会主持词 班会主持词(精选12篇)  根据活动对象的不同,需要设置不同的主持词。在如今这个时代,各种集会中主持...
学术研讨会主持词 学术研讨会主持词  什么是主持词  由主持人于节目进行过程中串联节目的串联词。如今的各种演出活动和集...
小学音乐会的主持稿 小学音乐会的主持稿范文  开场舞:群舞《仰望五星红旗》  叶XX:感谢14位同学给我们带来的精彩演出...
元旦主持词舞蹈串词 元旦主持词舞蹈串词  开场语:  华:尊敬的各位领导、各位来宾  蒋:亲爱的老师、同学们  杨:大家...