Android DataBinding三元条件设置dp尺寸边距编译报错问题
问题根因
该报错与尺寸资源使用dp还是sp定义无任何关联,本质是不同属性的DataBinding适配逻辑存在差异:
- 绑定表达式中直接书写
@dimen/xxx时,DataBinding会默认将尺寸资源解析为float类型的原始像素值 android:textSize对应View原生方法setTextSize(float),本身就接收float类型参数,直接传入解析出的float值完全匹配方法签名,因此可以正常运行android:layout_marginTop属于MarginLayoutParams的属性,框架没有为其提供接收float类型参数的公开setter,DataBinding拿到float类型值后找不到匹配的赋值方法,就会抛出参数类型不匹配的错误。实际验证可知:即便将sp单位的尺寸资源用于layout_marginTop属性,同样会触发该报错。
可行解决方案
任选其一即可解决问题:
- 方案1:使用DataBinding内置的dimen资源绑定适配器做显式转换
不要直接在三元表达式中书写@dimen/xxx,改为传递资源ID,用@dimen()包裹整个表达式,框架会自动完成资源到目标类型的适配转换:android:layout_marginTop="@{@dimen(landingManager.messageClickable ? R.dimen.spacing_2 : R.dimen.spacing_13)}" - 方案2:自定义BindingAdapter实现适配
编写一个接收float类型值的topMargin绑定方法,内部完成值到LayoutParams的设置逻辑:
该方法添加到项目后,原有代码无需任何修改即可正常编译运行。@BindingAdapter("android:layout_marginTop") @JvmStatic fun setTopMargin(view: View, topMargin: Float) { val layoutParams = view.layoutParams as? ViewGroup.MarginLayoutParams ?: return layoutParams.topMargin = topMargin.toInt() view.layoutParams = layoutParams } - 方案3:在绑定表达式中手动做类型转换
直接将dimen解析出的float值转为int类型,匹配LayoutParams的参数类型要求:
该方案需要注意float转int的精度损失问题,避免出现尺寸不符合预期的情况。android:layout_marginTop="@{(int)(landingManager.messageClickable ? @dimen/spacing_2 : @dimen/spacing_13)}"
补充说明:IDE中按住Ctrl可正常跳转至dimen资源声明,仅代表静态资源索引正常,和DataBinding编译阶段的类型匹配逻辑完全独立,不能作为绑定表达式写法正确的判断依据。
内容的提问来源于stack exchange,提问作者Jeff Hatfield
相关产品推荐
相关产品推荐

