自定义RelativeLayout按XML配置宽高比时比例始终为1或0问题求助
问题排查及修复方案
核心问题点
- 类型转换顺序错误:
int height = (int) ratio * widthMeasureSpec;代码中会先将float类型的ratio强转为int,比如ratio=0.5会被转成0,ratio=1.9会被转成1,这就是你获取到比例始终为0或1的直接原因 - 误用MeasureSpec参数:
widthMeasureSpec是Android封装的测量规格,不是实际的宽度数值,需要先解析出实际宽度值再计算高度 - 测量参数构造错误:计算得到的高度数值不能直接传入
super.onMeasure,需要构造符合规则的heightMeasureSpec - TypedArray回收逻辑错误:
a.recycle()放在try块内部,一旦前面代码抛出异常就会导致TypedArray无法回收,引发内存泄漏 - 代码冗余:三个带属性的构造函数重复编写了属性读取逻辑,可抽取为公共方法简化维护
修复后代码
CustomRelativeLayout.java
public class CustomRelativeLayout extends RelativeLayout { float ratio = 1f; public CustomRelativeLayout(Context context) { super(context); } public CustomRelativeLayout(Context context, AttributeSet attrs) { super(context, attrs); initAttrs(attrs); } public CustomRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initAttrs(attrs); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public CustomRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); initAttrs(attrs); } // 抽取公共属性初始化方法 private void initAttrs(AttributeSet attrs) { if (attrs == null) return; TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CustomRelativeLayout); try { ratio = a.getFloat(R.styleable.CustomRelativeLayout_ratio_pro, 1f); } catch (Exception e) { Log.i("Log1", "getLayout: " + e.toString()); } finally { // 回收放在finally块保证一定执行 a.recycle(); } requestLayout(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // 先解析出实际的宽度值 int actualWidth = MeasureSpec.getSize(widthMeasureSpec); // 先计算乘积再转int,避免ratio被提前强转丢失精度 int actualHeight = (int) (ratio * actualWidth); // 构造高度的MeasureSpec,模式设为EXACTLY表示使用我们计算的精确高度 int finalHeightSpec = MeasureSpec.makeMeasureSpec(actualHeight, MeasureSpec.EXACTLY); super.onMeasure(widthMeasureSpec, finalHeightSpec); } }
attrs.xml(原有逻辑无需修改,可正常使用)
<resources> <declare-styleable name="CustomRelativeLayout"> <attr name="ratio_pro" format="float"/> </declare-styleable> </resources>
XML布局使用示例
<!-- 比如宽高比设为16:9,ratio_pro就填9/16=0.5625 --> <com.yourpackage.CustomRelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" app:ratio_pro="0.5625" android:background="#f0f0f0"/>
内容的提问来源于stack exchange,提问作者pouya
相关产品推荐
相关产品推荐

