[英]How to wrap height of Android ViewPager2 to height of current item?
這個問題是針對新的ViewPager2類的。
舊的 ViewPager也有類似的問題,但解決方案需要擴展ViewPager 。 但是,ViewPager2 是最終版本,因此無法擴展。
在我的情況下,我有一個包含三個不同片段的 ViewPager2。 其中一個片段比其他兩個片段高得多,這意味着當你滑動到較短的片段之一時,會有很多空白空間。 那么如何有效地將 ViewPager2 包裹到當前片段的高度呢?
解決方案是在屬於ViewPager2
每個片段中添加以下ViewPager2
:
override fun onResume() {
super.onResume()
binding.root.requestLayout()
}
binding.root
是ViewBinding /數據綁定,但它是你的布局,即主容器ConstraintLayout
, LinearLayout
,等
我對這個解決方法一點也不滿意,但它確實解決了我在嘗試使用具有不同高度片段的 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
}
}
我有同樣的問題,ViewPager2 在 ScrollView 中,它在 TabLayout 下。 瀏覽選項卡后,ScrollView 的高度變得等於最大片段高度的高度。 問題是通過將 ScrollView 轉移到片段來解決的。
花了很多時間后,這對我Nesterscrollview
,我的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
}
}
}
}
基於Lucas Nobile,我發現了另一種實現方式。 而不是將以下代碼放在每個受影響片段的 OnResume 方法上:
override fun onResume() {
super.onResume()
binding.root.requestLayout()
}
只需將此覆蓋添加到 viewPager2 的適配器:
override fun onBindViewHolder(
holder: FragmentViewHolder,
position: Int,
payloads: MutableList<Any>
){
holder.itemView.requestLayout()
super.onBindViewHolder(holder, position, payloads)
}
Obs:用 kotlin 編寫的代碼。
對我來說,設置 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));
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">
//您的子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>
我能夠通過覆蓋 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 的布局高度都是環繞內容。
我有動態頁面高度的問題,這可能會在運行時發生變化。 換頁后,最高頁的部分內容被截斷。
我能夠通過重新測量尋呼機內容(即頁面)和尋呼機本身來解決這個問題。
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()
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.