如何根据 ViewPager 当前页面的不同设置其高度

如何根据 ViewPager 当前页面的不同设置其高度,第1张

{

UNREFERENCED_PARAMETER(lParam)

switch (message)

{

case WM_INITDIALOG:

return (INT_PTR)TRUE

case WM_COMMAND:

if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)

{

EndDialog(hDlg, LOWORD(wParam))

return (INT_PTR)TRUE

}

break

}

return (INT_PTR)FALSE

}

    步骤1:将ViewPager与其同一容器内的其它View,使用权重约束。~~~~~未果,效果依然如常态

    步骤2:将ViewPager 的高度设置为具体的数值。~~~~~解决问题,但是,偏离了使用wrap_content的初衷。

    步骤2:将ViewPager 的 item root view设置固定的高度值。~~~~~未果,效果依然如常态。

    步骤3:在Adapter 创建对象的函数中(也就是添加item view的地方),获取到Item root view的子View,并且获取其,宽度、高度,并在此设置 View(instantiateItem 函数  所返回的View) 的宽、高,~~~~~~未果,效果依然如常态

     步骤4:此方案类似与“步骤3”,唯一区别的是高亮显示的区域

    在Adapter 创建对象的函数中(也就是添加item view的地方),获取到Item root view的子View,并且获取其,宽度、高度,并在此设置 container(instantiateItem  函数 所传递的container ) 的宽、高,~~~~~~得偿所愿,效果实现

    Note:注意获取View的高度,需要view.post(new Runnable(){    //get view height  }) 在Runnable体内获取高度、宽度

ViewPager高度设置为wrap_content或者具体的高度值无效,是因为ViewPager的onMeasure方法在度量宽高的时候,在方法体的最开始就直接调用了setMeasuredDimension()方法将自身的宽高度量,但是并没有在其onMeasure()计算完其具体的子View的宽高之后,重新度量一次自身的宽高

从这里我们可以看到,ViewPager的宽高会受其父容器的宽高的限制,但是并不会因为自身子View的宽高而影响ViewPager的宽高。

看setMeasuredDimension的源码调用可以看出,当父容器的高度确定时,ViewPager的宽高其实就是父容器的宽高,ViewPager就是在onMeasure方法一进来的时候就直接填充满整个父容器的剩余空间。在计算孩子节点之前,就已经计算好了ViewPager的宽高,在计算完孩子节点之后,并不会再去重新计算ViewPager的宽高。

自定义一个ViewPager,根据子View的宽高重新度量ViewPager的宽高。其实做法就是在自定义onMeasure的super.onMeasure(widthMeasureSpec, heightMeasureSpec)之前重新计算heightMeasureSpec,将原本ViewPager接收的父容器的限定的heightMeasureSpec替换成我们自定义的heightMeasureSpec。

但是这样的做法,会有种问题,即在ViewPager的子View是采用LinearLayout作为根布局的时候,并且给LinearLayout设置了固定的高度值,那么会出现ViewPager动态高度无效的问题

其实具体的做法,就是仿造measureChild的做法,自定义子View的heightMeasureSpec然后度量整个子View,其实子View的宽度也可以这样做。

这里其实是源码层做了限制,在setOffscreenPageLimit中设置了一个默认值,而这个默认值的大小为1

所以从这里可以看出,ViewPager的最小缓存的limit是1,而不能小于1,当小于1的时候就会被强制的设置为1。

而populate()函数就是用来处理ViewPager的缓存的。

populate()的生命周期是与Adapter的生命周期绑定的。

其实在setOffscreenPageLimit()的时候,调用的populate(),而populate()内部调用的

而pupulate(int newCurrentItem)方法在另一处调用的地方就是在setCurrentItem。

其实ViewPager缓存都是基于ItemInfo这个类来进行的,

看下ViewPager.addNewItem的源码

其实ViewPager.addNewItem就是通过调用Adapter.instantiateItem来创建对应的View,并且将View保存到ItemInfo中的object属性,并且判断ViewPager缓存中是否已经有ItemInfo,如果没有,则添加,如果有则做修改替换

从分析FragmentStatePagerAdapter来看,setUserVisibleHint方法会优先于Fragment的生命周期函数 执行。因为在FragmentStatePagerAdapter中提交事务,是在调用finishUpdate方法中进行的,只有提交事务的时候,才会去执行Fragment的生命周期。

FragmentStatePagerAdapter中的instantiateItem和destroyItem都实现了对fragment的事务的添加和删除,而finishUpdate实现了事务的提交,所以在实现FragmentStatePagerAdapter的时候,并不需要重写instantiateItem和destroyItem


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/11143490.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-13
下一篇 2023-05-13

发表评论

登录后才能评论

评论列表(0条)

保存