有几篇文章介绍了如何使ViewPager与高度不同的项目一起使用,其重点是扩展ViewPager
本身以修改其onMeasure
以支持这一点。
但是,鉴于 ViewPager2
被标记为最后一堂课,扩展它不是我们可以做的事情。
有人知道是否有办法解决这个问题吗?
View1 = 200dp
View2 = 300dp
加载ViewPager2(layout_height="wrap_content"
)时-看着View1,其高度将为200dp。
但是当我滚动到View2时,高度仍然是200dp; View2的最后100dp被切断。
答案 0 :(得分:3)
就我而言,在adapter.notifyDataSetChanged()
中添加onPageSelected
很有帮助。
答案 1 :(得分:3)
我本人偶然发现了这个片段。 我决定将视图包装在ConstraintLayout中,而不是将视图调整为可接受的答案。这要求您指定ViewPager2的大小,而不要使用wrap_content。
因此,不必更改viewpager的大小,它必须是它处理的最大视图的最小大小。
Android有点新,所以不知道这是否是一个好的解决方案,但这对我有用。
换句话说:
<androidx.constraintlayout.widget.ConstraintLayout
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="match_parent"
>
<!-- Adding transparency above your view due to wrap_content -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
>
<!-- Your view here -->
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
答案 2 :(得分:1)
解决方案是在孩子要求自己重新测量后,注册PageChangeCallback
并调整LayoutParams
的{{1}}。
ViewPager2
或者,如果您的视图的高度由于某些原因而在某些时候发生变化,异步数据加载,然后改用全局布局侦听器:
pager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
val view = // ... get the view
view.post {
val wMeasureSpec = MeasureSpec.makeMeasureSpec(view.width, MeasureSpec.EXACTLY)
val hMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
view.measure(wMeasureSpec, hMeasureSpec)
if (pager.layoutParams.height != view.measuredHeight) {
// ParentViewGroup is, for example, LinearLayout
// ... or whatever the parent of the ViewPager2 is
pager.layoutParams = (pager.layoutParams as ParentViewGroup.LayoutParams)
.also { lp -> lp.height = view.measuredHeight }
}
}
}
}
查看此处的讨论:
答案 3 :(得分:1)
对我来说,这很完美:
viewPager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
super.onPageScrolled(position,positionOffset,positionOffsetPixels)
if (position>0 && positionOffset==0.0f && positionOffsetPixels==0){
viewPager2.layoutParams.height =
viewPager2.getChildAt(0).height
}
}
})
答案 4 :(得分:1)
@sonique 有一个非常详细的答案,这里有解释。
https://stackoverflow.com/a/64235840/2867351
基本上,您应该尝试做的是在 onPageSelected()
时动态计算高度。
您可以使用 ViewPager2
轻松访问 childFragmentManager
中的视图。
确保您的子片段 layout_height
是 wrap_content
。否则,当视图尝试测量其高度时,您会看到奇怪的行为。
我通过艰难的方式学会了它。
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
if (childFragmentManager.fragments.size > position) {
val fragment = childFragmentManager.fragments.get(position)
fragment.view?.let {
updatePagerHeightForChild(it, viewPager)
}
}
}
fun updatePagerHeightForChild(view: View, pager: ViewPager2) {
view.post {
val widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(
view.width, View.MeasureSpec.EXACTLY
)
val heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(
0, View.MeasureSpec.UNSPECIFIED
)
view.measure(widthMeasureSpec, heightMeasureSpec)
if (pager.layoutParams.height != view.measuredHeight) {
pager.layoutParams = (pager.layoutParams).also {
it.height = view.measuredHeight
}
}
}
}
})
答案 5 :(得分:1)
@Mephoros 代码在视图之间滑动时可以完美运行,但在第一次查看视图时不起作用。滑动后即可正常工作。
因此,以编程方式滑动viewpager:
binding.viewpager.setCurrentItem(1)
binding.viewpager.setCurrentItem(0) //back to initial page
答案 6 :(得分:1)
只需为 Fragment
中所需的 ViewPager2
执行此操作:
override fun onResume() {
super.onResume()
layoutTaskMenu.requestLayout()
}
答案 7 :(得分:0)
没有发布的答案完全适用于我的情况 - 事先不知道每个页面的高度 - 所以我在下面使用 ViewPager2
解决了不同的 ConstraintLayout
页面高度方式:
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
>
<!-- ... -->
</com.google.android.material.appbar.AppBarLayout>
<!-- Wrapping view pager into constraint layout to make it use maximum height for each page. -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/viewPagerContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/bottomNavigationView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/appBarLayout"
>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNavigationView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="@menu/bottom_navigation_menu"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
答案 8 :(得分:0)
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
val view = (viewPager[0] as RecyclerView).layoutManager?.findViewByPosition(position)
view?.post {
val wMeasureSpec = MeasureSpec.makeMeasureSpec(view.width, MeasureSpec.EXACTLY)
val hMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
view.measure(wMeasureSpec, hMeasureSpec)
if (viewPager.layoutParams.height != view.measuredHeight) {
viewPager.layoutParams = (viewPager.layoutParams).also { lp -> lp.height = view.measuredHeight }
}
}
}
})
答案 9 :(得分:0)
只需在 ViewPager2 中使用的 Fragment 类的 .requestLayout()
中将 onResume()
调用到布局的根视图