此问题是针对新的 ViewPager2 类。
有一个similar question for the old ViewPager,但是解决方案需要扩展 ViewPager 。但是,ViewPager2是最终版本,因此无法扩展。
在我的情况下,我有一个包含三个不同片段的ViewPager2。这些片段中的一个比其他两个片段高得多,这意味着当您滑动到一个较短的片段中时,会有很多空白。那么如何有效地将ViewPager2包装到当前片段的高度?
答案 0 :(得分:2)
我对这种解决方法一点都不满意,但是它确实解决了我尝试将ViewPager2与不同高度的片段一起使用时的渲染问题。显然,它将减慢渲染速度并消耗更多内存。
myStupidViewPager2.offscreenPageLimit = fragments.size
答案 1 :(得分:2)
解决方案是在ViewPager2
的每个片段中添加以下内容:
override fun onResume() {
super.onResume()
binding.root.requestLayout()
}
binding.root
来自ViewBinding / DataBinding,但它是布局的主要容器,即ConstraintLayout
,LinearLayout
等。
答案 2 :(得分:1)
花了很多时间后,这对我有用,我的 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) }
}
})
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
}
}
}
}
答案 3 :(得分:0)
对我来说,设置viewpager2的recyclerview布局参数可以解决此问题。
尝试
<androidx.viewpager2.widget.ViewPager2
android:layout_width="match_parent"
android:layout_height="wrap_content" />
并设置recyclerview布局参数
RecyclerView recyclerView = (RecyclerView) viewPager.getChildAt(0);
recyclerView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
答案 4 :(得分:0)
我找到了这个问题的答案,当我通过适配器访问孩子时,就像在任何给定位置访问孩子而不是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
}
}
}
}
pagerpager.registerOnPageChangeCallback(ViewPager2PageChangeCallback())
override fun onDestroy() {
super.onDestroy()
pager.unregisterOnPageChangeCallback(ViewPager2PageChangeCallback())
}
答案 5 :(得分:0)
我遇到了同样的问题,ViewPager2在ScrollView中,它位于TabLayout下。在选项卡中浏览后,ScrollView的高度等于最大片段高度的高度。 通过将ScrollView转移到片段可以解决此问题。
答案 6 :(得分:0)
https://gist.github.com/safaorhan/1a541af729c7657426138d18b87d5bd4
这对我有用;
感谢我为我所做的这项工作,当我们想使用 viewpager 作为 Book 页面时。有不同种类的页面高度。有时,当页面太长时,我们需要滚动操作:3 那时,只需使用 NestedScroll View 包裹您的 viewpager 的项目布局即可..
感谢@safaorhan
/** * 禁用子附加侦听器,以便具有 wrap_content 高度的膨胀的孩子可以通过。 * * 这很脆弱,取决于[ViewPager2]的实现细节。 * * @see 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">
//您的子浏览器项目
<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>
答案 7 :(得分:0)
通过覆盖 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 的布局如下(在 NestedScrollView 内)
<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>
另外,请确保所有 Fragment 的布局高度都是环绕内容。
答案 8 :(得分:0)
我有动态页面高度的问题,这可能会在运行时发生变化。换页后,最高页的部分内容被截断。
我能够通过重新测量寻呼机内容(即页面)和寻呼机本身来解决这个问题。
viewPager2.setPageTransformer { page, _ ->
val wMeasureSpec =
View.MeasureSpec.makeMeasureSpec(page.width, View.MeasureSpec.EXACTLY)
val hMeasureSpec =
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
page.measure(wMeasureSpec, hMeasureSpec)
measure(wMeasureSpec, hMeasureSpec)
post {
adapter?.notifyDataSetChanged()
}
}