Android ViewPager设置layout_height为wrap_content不生效问题求助
问题根因与解决方案
第一步:修正布局中的冲突属性
你当前的ViewPager同时配置了android:layout_below="@id/main_toolbar"和android:layout_alignParentBottom="true"两个属性,在RelativeLayout中同时设置上下对齐约束时,ViewPager的高度会直接被拉伸为两个约束之间的全部空间,wrap_content属性会直接失效。
你可以先删除android:layout_alignParentBottom="true"这行代码,先验证是否解决问题,如果删除后还是达不到自适应高度的效果,再执行第二步。
第二步:使用支持wrap_content的自定义ViewPager
原生AndroidX ViewPager默认没有做wrap_content适配,测量时不会计算子Fragment的高度,所以需要自定义ViewPager重写测量逻辑,代码如下:
// Kotlin版本自定义ViewPager import android.content.Context import android.util.AttributeSet import android.view.View import androidx.viewpager.widget.ViewPager class WrapContentHeightViewPager @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null ) : ViewPager(context, attrs) { override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { var height = 0 // 遍历所有子View计算最高的子View高度 for (i in 0 until childCount) { val child: View = getChildAt(i) child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)) val h: Int = child.measuredHeight if (h > height) height = h } val newHeightMeasureSpec = if (height != 0) { MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY) } else { heightMeasureSpec } super.onMeasure(widthMeasureSpec, newHeightMeasureSpec) } }
如果使用Java开发,代码如下:
// Java版本自定义ViewPager import android.content.Context; import android.util.AttributeSet; import android.view.View; import androidx.viewpager.widget.ViewPager; public class WrapContentHeightViewPager extends ViewPager { public WrapContentHeightViewPager(Context context) { super(context); } public WrapContentHeightViewPager(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int height = 0; for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); int h = child.getMeasuredHeight(); if (h > height) height = h; } int newHeightMeasureSpec = height != 0 ? MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY) : heightMeasureSpec; super.onMeasure(widthMeasureSpec, newHeightMeasureSpec); } }
第三步:替换布局中的ViewPager声明
把你布局里的androidx.viewpager.widget.ViewPager替换成你刚才写的自定义ViewPager的全类名即可,示例如下:
<你的代码包名.WrapContentHeightViewPager android:id="@+id/viewpager" app:layout_behavior="@string/appbar_scrolling_view_behavior" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="@dimen/standard_margin_x2" android:layout_below="@id/main_toolbar" android:layout_alignParentLeft="true" />
可选适配方案(3个Fragment高度不一致时使用)
上面的自定义ViewPager默认会取所有Fragment里最高的那个作为固定高度,如果需要切换Fragment时动态适配当前Fragment的高度,可以给ViewPager添加页面切换监听,切换时重新触发测量即可:
viewpager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener { override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {} override fun onPageSelected(position: Int) { // 切换页面时请求重新测量 viewpager.requestLayout() } override fun onPageScrollStateChanged(state: Int) {} })
内容的提问来源于stack exchange,提问作者Azerbaijani Turk
相关产品推荐
相关产品推荐

