求助:如何解决旧版Android API中PercentRelativeLayout显示异常问题
这问题确实够棘手的——老项目用了已经废弃的PercentRelativeLayout,没法全盘重写,还偏偏在5.1.1设备上掉链子。我之前也碰到过类似的兼容性坑,给你几个不用大改代码的解决方案:
1. 检查并更新Percent支持库版本
首先确认你的项目里依赖的com.android.support:percent库版本是不是太老了。Android 5.1.1对早期版本的Percent布局库有解析bug,建议升级到28.0.0(这是support库的最终稳定版,兼容5.0+):
implementation 'com.android.support:percent:28.0.0'
如果已经是这个版本,试试clean项目、清除缓存再重新编译,有时候缓存会导致奇奇怪怪的兼容性问题。
2. 对出问题的视图动态设置尺寸
如果升级库没用,可以在代码里手动计算百分比尺寸,绕开系统的布局解析bug。比如在Activity的onCreate或者Fragment的onViewCreated里,等父布局完成测量后再设置子View的参数:
// 找到你的PercentRelativeLayout父容器 PercentRelativeLayout parentLayout = findViewById(R.id.your_parent_layout); parentLayout.post(new Runnable() { @Override public void run() { int parentWidth = parentLayout.getWidth(); int parentHeight = parentLayout.getHeight(); // 找到不显示的子View View targetView = findViewById(R.id.problematic_view); PercentRelativeLayout.LayoutParams params = (PercentRelativeLayout.LayoutParams) targetView.getLayoutParams(); // 按照你原本的百分比设置,比如宽度70%,高度30% params.width = (int) (parentWidth * 0.7f); params.height = (int) (parentHeight * 0.3f); targetView.setLayoutParams(params); } });
这个方法的好处是不用改布局文件,只针对有问题的视图处理,侵入性很低。
3. 自定义兼容版PercentRelativeLayout
如果很多页面都有问题,写个自定义布局来替代系统的PercentRelativeLayout,手动处理百分比属性的解析:
首先在res/values/attrs.xml里定义百分比属性:
<declare-styleable name="CustomPercentLayout"> <attr name="layout_widthPercent" format="float" /> <attr name="layout_heightPercent" format="float" /> </declare-styleable>
然后写自定义布局类:
public class CustomPercentRelativeLayout extends RelativeLayout { public CustomPercentRelativeLayout(Context context) { super(context); } public CustomPercentRelativeLayout(Context context, AttributeSet attrs) { super(context, attrs); } public CustomPercentRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int parentWidth = MeasureSpec.getSize(widthMeasureSpec); int parentHeight = MeasureSpec.getSize(heightMeasureSpec); // 遍历子View,处理百分比属性 for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); LayoutParams params = (LayoutParams) child.getLayoutParams(); TypedArray ta = getContext().obtainStyledAttributes( params.getAttributes(), R.styleable.CustomPercentLayout); float widthPercent = ta.getFloat(R.styleable.CustomPercentLayout_layout_widthPercent, 0f); float heightPercent = ta.getFloat(R.styleable.CustomPercentLayout_layout_heightPercent, 0f); ta.recycle(); if (widthPercent > 0) { params.width = (int) (parentWidth * widthPercent); } if (heightPercent > 0) { params.height = (int) (parentHeight * heightPercent); } } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }
最后把布局里的PercentRelativeLayout替换成这个自定义类:
<com.yourpackage.CustomPercentRelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="0dp" android:layout_height="0dp" app:layout_widthPercent="0.5" app:layout_heightPercent="0.2" android:text="测试文本"/> </com.yourpackage.CustomPercentRelativeLayout>
这个自定义布局完全避开了系统库的bug,而且用法和原来的PercentRelativeLayout几乎一致,改起来很快。
4. 针对5.1.1做版本适配
如果只有5.1.1设备出问题,可以在代码里判断系统版本,只在该版本下启用兼容逻辑:
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1) { // 执行上面的动态设置尺寸逻辑,或者切换到自定义布局 }
这样不会影响其他正常设备的运行。
这些方法都不用全盘重写你的布局,只需要针对性修改,应该能解决你遇到的问题。
内容的提问来源于stack exchange,提问作者Andrew1410

