【Android】ViewPager2切换fragment时高度无法自适应问题


前言

在这里插入图片描述
tab选项、底部或者顶部的导航栏、菜单栏 点击时都需要去切换fragment页面,可以有以下实现方式:

  1. 可以使用FrameLayout控件手动切换(不可滑动,滑动需单独实现)
  2. 使用viewpage2自动切换(可以滑动)

一、问题

ViewPage2是Jetpack中的其中一个组件,可以实现滑动切换页面的效果,通常可以搭配其他组件实现滑动切换效果。ViewPager2是基于RecyclerView实现的,自然继承了RecyclerView的众多优点,并且针对ViewPager存在的问题做了优化。可以使用offscreenPageLimi属性来预先加载页面,也可设置为0实现懒加载(页面显示时再加载)。
在这里插入图片描述

但是在实际开发中遇到一个问题:

ViewPager2下多个fragment的页面高度可能是不同的,在允许预加载的条件下ViewPager2的高度会始终跟随最高的那个fragment的高度,导致其他比较低的fragment页面出现留白的问题。即便禁止了预加载,也不能解决。

二、解决

1. ViewPage2添加配置

如果要实现ViewPage2的高度始终和当前的fragment保持一致,那么就需要在每一次点击tab的时候重新计算当前fragment的高度并将高度设置给ViewPage2。

vp2_frag是ViewPage2控件,fragmentList是所有fragment的集合

			private val fragmentList = arrayListOf<Fragment>()
			
			......
			
			//viewPager初始化以及切换tab的时候都会触发这个监听,不管是否禁止了预加载都不会有影响
            vp2_frag.viewTreeObserver.addOnGlobalLayoutListener {
    
    
                if(fragmentList.size>0){
    
    
                    updatePagerHeightForChild(fragmentList[vp2_frag.currentItem].view, vp2_frag)
                }
            }
            
            vp2_frag.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback(){
    
    
                override fun onPageSelected(position: Int) {
    
    
                    //切换页面效果
                    super.onPageSelected(position)
                    updatePagerHeightForChild(fragmentList[vp2_frag.currentItem].view, vp2_frag)
                }
            })
            
	//自适应高度,计算fragment的高度并设置给viewPager
    private fun updatePagerHeightForChild(view: View?, pager: ViewPager2) {
    
    
        view?.post {
    
    
            //设置尺寸和模式的测量规则
            val wMeasureSpec = View.MeasureSpec.makeMeasureSpec(view.width, View.MeasureSpec.EXACTLY)
            val hMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
            view.measure(wMeasureSpec, hMeasureSpec)
            if (pager.layoutParams.height != view.measuredHeight) {
    
    
                pager.layoutParams = pager.layoutParams.also {
    
     lp ->
                    lp.height = view.measuredHeight
                }
            }
        }
    }

不允许预加载时,点击tab的时候onItemSelect方法可能会比创建Fragment更早的执行,导致拿不到fragment。

允许预加载之后,ViewPage2加载完成后它的高度仍然跟随最高的那个fragment,点击tab重新计算高度的代码没有执行,从而导致第一个fragment可能留白。

所以需要在一个可以监听到ViewPage2初始化又可以监听到ViewPage2切换的地方调用updatePagerHeightForChild方法。

2. 换成手动切换

使用FrameLayout去手动切换,重新加载页面:

<FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginBottom="0dp"/>

在activity中使用:R.id.content是FrameLayout

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/T01151018/article/details/139272141