如何将Android ViewPager2的高度包装到当前项目的高度?
此问题适用于新的查看页面2类 存在一个,但解决方案需要扩展ViewPager。但是,ViewPager2是最终版本,因此无法扩展如何将Android ViewPager2的高度包装到当前项目的高度?,android,android-fragments,android-viewpager,android-viewpager2,Android,Android Fragments,Android Viewpager,Android Viewpager2,此问题适用于新的查看页面2类 存在一个,但解决方案需要扩展ViewPager。但是,ViewPager2是最终版本,因此无法扩展 在我的情况下,我有一个ViewPager2,它包含三个不同的片段。其中一个碎片比另外两个碎片高很多,这意味着当你滑动到其中一个较短的碎片时,会有很多空白。那么,如何有效地将ViewPager2包装到当前片段的高度呢?对于我来说,设置ViewPager2的recyclerview布局参数可以解决这个问题 试一试 我对这种解决方法一点也不满意,但它确实解决了我在尝试使用V
在我的情况下,我有一个ViewPager2,它包含三个不同的片段。其中一个碎片比另外两个碎片高很多,这意味着当你滑动到其中一个较短的碎片时,会有很多空白。那么,如何有效地将ViewPager2包装到当前片段的高度呢?对于我来说,设置ViewPager2的recyclerview布局参数可以解决这个问题 试一试
我对这种解决方法一点也不满意,但它确实解决了我在尝试使用ViewPager2处理不同高度片段时遇到的渲染问题。这显然会降低渲染速度并消耗更多内存
myStupidViewPager2.offscreenPageLimit = fragments.size
我已经找到了这个问题的答案,我通过它的适配器访问子对象,就像在任何给定位置访问子对象而不是Zer0索引时,视图为空
class ViewPager2PageChangeCallback() : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
val view = (pager.adapter as pagerAdapter).getViewAtPosition(position)
view?.let {
updatePagerHeightForChild(view, pager)
}
}
}
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
}
}
}
}
pager.offscreenPageLimit = 1
pagerpager.registerOnPageChangeCallback(ViewPager2PageChangeCallback())
override fun onDestroy() {
super.onDestroy()
pager.unregisterOnPageChangeCallback(ViewPager2PageChangeCallback())
}
class OrderDetailsPager(
private val arrayList: ArrayList<Fragment>,
fragmentManger: FragmentManager,
lifecycle: Lifecycle
) : FragmentStateAdapter(fragmentManger, lifecycle) {
override fun createFragment(position: Int): Fragment {
return arrayList[position]
}
override fun getItemCount(): Int {
return arrayList.size
}
fun getViewAtPosition(position: Int): View? {
return arrayList[position].view
}
}
类ViewPager2PageChangeCallback():ViewPager2.OnPageChangeCallback(){
覆盖所选页面(位置:Int){
val视图=(pager.adapter作为pagerAdapter)。getViewAtPosition(位置)
风景?让我看看{
updatePagerHeightForChild(视图、寻呼机)
}
}
}
private fun updatePagerHeightForChild(查看:查看,寻呼机:查看页面2){
view.post{
val wMeasureSpec=
View.MeasureSpec.makeMeasureSpec(View.width,View.MeasureSpec.justice)
val hMeasureSpec=View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED)
视图.度量(wMeasureSpec,hMeasureSpec)
if(pager.layoutParams.height!=视图.测量高度){
pager.layoutParams=(pager.layoutParams)
。同时{lp->
lp.height=视图测量高度
}
}
}
}
pager.offscreenPageLimit=1
pagerpager.registerOnPageChangeCallback(ViewPager2PageChangeCallback())
重写onDestroy(){
super.ondestory()
pager.unregisterOnPageChangeCallback(ViewPager2PageChangeCallback())
}
类OrderDetailsPage(
private val arrayList:arrayList,
碎片经理:碎片经理,
生命周期:生命周期
):FragmentStateAdapter(FragmentManager,生命周期){
重写片段(位置:Int):片段{
返回数组列表[位置]
}
重写getItemCount():Int{
返回arrayList.size
}
有趣的getViewAtPosition(位置:Int):查看{
返回arrayList[位置].视图
}
}
我也遇到了同样的问题,ViewPager2在ScrollView中,它位于TableLayout下。在通过选项卡导航后,ScrollView的高度等于最大片段高度的高度。
通过将ScrollView传输到片段解决了此问题。解决方案是在属于
ViewPager2
的每个片段中添加以下内容:
override fun onResume() {
super.onResume()
binding.root.requestLayout()
}
binding.root
来自ViewBinding/DataBinding,但它是布局的主要容器,即ConstraintLayout
,LinearLayout
,等等。
这是我的工作
感谢这项工作为我,当我们想使用viewpager作为书的'页。有不同种类的页面高度。有时,当页面太长时,我们需要滚动操作:3此时,只需使用NestedScroll视图包装viewpager的项目布局
感谢@safaorhan
/**
*禁用子附加侦听器,以便具有换行内容高度的充气子对象可以通过。
*
*这非常脆弱,取决于[ViewPager2]的实现细节。
*
*@请参阅ViewPager2.enforceChildFillListener(已删除的侦听器)
*/
//使用viewpager调用此方法
private fun ViewPager2.hackMatchParentCheckInViewPager() {
(getChildAt(0) as RecyclerView).clearOnChildAttachStateChangeListeners()
}
//查看寻呼机
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/page_view_pager"
android:layout_width="match_parent"
android:layout_height="0dp">
//您的子Viewpager项
<androidx.core.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
....
</LinearLayout>
</androidx.core.widget.NestedScrollView>
....
这对我来说很有效。在花了很多时间之后,我的viewpager2
位于Nesterscrollview
binding.viewpager.offscreenPageLimit = 2
binding.viewpager.isUserInputEnabled = false
binding.viewpager.registerOnPageChangeCallback(object :ViewPager2.OnPageChangeCallback(){
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
val myFragment = childFragmentManager.findFragmentByTag("f$position")
myFragment?.view?.let { updatePagerHeightForChild(it,binding.viewpager) }
}
})
我可以通过覆盖onPageSelected回调并重新测量当前视图的高度来做到这一点 它看起来像这样:
mViewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
mTabLayout.selectTab(mTabLayout.getTabAt(position));
View view = mViewPagerAdapter.getViewAtPosition(position); // this is a method i have in the adapter that returns the fragment's view, by calling fragment.getview()
if (view != null) {
view.post(() -> {
int wMeasureSpec = View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY);
int hMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(wMeasureSpec, hMeasureSpec);
viewPager.getLayoutParams().height = view.getMeasuredHeight();
mViewPagerAdapter.notifyDataSetChanged();
});
}
}
});
mViewPager.setOffscreenPageLimit(mTabLayout.getTabCount());
TabLayout和Viewpager2的布局如下所示(在嵌套的ScrollView中)
另外,请确保所有片段的布局高度都是包装内容。请发布代码和截图。你能理解吗?@Kimble还没有:-(另请参阅和。谢谢,但这对我不起作用。我所有的ViewPager2页面都随此代码一起消失了。也就是说,我的页面现在是视图(而不是片段),因此您的答案可能对其他人有用。
viewPager.setOffscreenPageLimit(3);
对我不起作用。但是,我的页面现在是视图(而不是片段),因此,您的答案可能对其他人有用。您实际在哪里调用此方法?好主意,但不处理延迟加载的项目(如分页)这不起作用,什么是getViewAtPosition和pagerAdapter?代码非常糟糕。getViewAtPosition作为在pagerAdapter(View pager2适配器)中添加的方法@AssemMahrous能否请您更新示例代码以同时显示getViewAtPosition和pagerAdapter,因为我对这些代码的来源感到困惑。我已经编辑了代码并添加了寻呼机适配器@Sphrake为什么您要在onDestroy
:pager.unregisterOnPageChangeCallback(ViewPager2PageChangeCallback)中再次创建回调())
?哈,这很有趣。你能解释一下这个代码到底是做什么的吗……它解决了我的问题,但我不明白为什么
binding.viewpager.offscreenPageLimit = 2
binding.viewpager.isUserInputEnabled = false
binding.viewpager.registerOnPageChangeCallback(object :ViewPager2.OnPageChangeCallback(){
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
val myFragment = childFragmentManager.findFragmentByTag("f$position")
myFragment?.view?.let { updatePagerHeightForChild(it,binding.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
}
}
}
}
mViewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
mTabLayout.selectTab(mTabLayout.getTabAt(position));
View view = mViewPagerAdapter.getViewAtPosition(position); // this is a method i have in the adapter that returns the fragment's view, by calling fragment.getview()
if (view != null) {
view.post(() -> {
int wMeasureSpec = View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY);
int hMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
view.measure(wMeasureSpec, hMeasureSpec);
viewPager.getLayoutParams().height = view.getMeasuredHeight();
mViewPagerAdapter.notifyDataSetChanged();
});
}
}
});
mViewPager.setOffscreenPageLimit(mTabLayout.getTabCount());
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/data_collection_tab_layout"
android:layout_width="match_parent"
android:layout_marginBottom="12dp"
android:layout_height="wrap_content" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/data_collection_viewpager2"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>