[英]Android ViewPager2 not dynamically wrapping height of different sized fragments
我有一個 ViewPager2 作為孩子有不同高度的片段,加載數據后孩子的高度會發生變化
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:expandedTitleGravity="top"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs_header"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="@string/prospect_detail_tab_prospect" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="@string/prospect_detail_tab_influencers" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="@string/prospect_detail_tab_sales" />
</com.google.android.material.tabs.TabLayout>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager_header"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</com.google.android.material.appbar.CollapsingToolbarLayout>
我已經嘗試了幾種不同的解決方案,但是如果 viewpager2 回到一個較小的片段,則沒有任何效果可以調整它的大小,它只是保持與最高片段相同的高度
當片段的高度發生變化時,ViewPager2 不會刷新自己的高度(例如,如果您在內部使用 RecyclerView)。
為了解決這個問題,我們需要計算用戶select標簽頁時的高度。 這可以使用registerOnPageChangeCallback和onPageSelected
來完成
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
// Here we need to calculate height
}
})
現在,我們需要計算片段的高度。 為此,我們需要訪問片段及其根視圖。 這可以使用提供給您的 ViewPagerAdapter 的 fragmentManager 來完成,在創建它時,例如這里我們使用 childFragmentManager: PagerViewAdapter(childFragmentManager, lifecycle)
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
// Because the fragment might or might not be created yet,
// we need to check for the size of the fragmentManager
// before accessing it.
if (childFragmentManager.fragments.size > position) {
val fragment = childFragmentManager.fragments.get(position)
fragment.view?.let {
// Now we've got access to the fragment Root View
// we will use it to calculate the height and
// apply it to the ViewPager2
updatePagerHeightForChild(it, binding.viewPager)
}
}
}
})
// This function can sit in an Helper file, so it can be shared across your project.
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 ->
// applying Fragment Root View Height to
// the pager LayoutParams, so they match
lp.height = view.measuredHeight
}
}
}
}
注意:我們正在使用綁定訪問viewPager
,如果您不使用綁定,請以您自己的方式提供viewPager,可能使用findViewById()
限制:異步加載內容
如果您有一些動態加載內容,您可能需要結合解決方案與ViewTreeObserver.OnGlobalLayoutListener
,我還沒有測試過。
您需要稍微自定義 ViewPager:
public class WrapHeightViewPager extends ViewPager {
private int currentPosition = 0;
public WrapHeightViewPager(@NonNull Context context) {
super(context);
}
public WrapHeightViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (currentPosition < getChildCount()) {
View child = getChildAt(currentPosition);
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int height = child.getMeasuredHeight();
if (height != 0) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
}
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public void measureViewPager(int currentPosition) {
this.currentPosition = currentPosition;
requestLayout();
}
}
之后,在初始化tabLayout時,只需在onTabSelected
function中調用measureViewPager(currentPosition)
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.measureViewPager(tab.getPosition());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.