原因:
首先要知道的是,DataBinding库已经提供了位于android.databinding.adapters.Converters.convertColorToDrawable(int)
的convertColorToDrawable
绑定转换器。
使用android:background
理论上应该可以工作,因为它有对应的setBackground(Drawable)
方法。问题在于它会看到你试图将一个颜色作为第一个参数传递,所以会在应用到setBackground(Drawable)
方法之前尝试启动此转换器。如果数据绑定决定使用转换器,则它将在两个参数上同时使用它,因此也会在应用最终结果到setter之前,在null
上使用它。
因为null
无法转换为int
(也无法调用intValue()
),所以会抛出NullPointerException
。
官方的Data Binding指南中提到,不支持混合参数类型。
以下是这个问题的两个解决方案。虽然您可以使用这两种任意一种解决方案,但第一种更容易实现。
解决方案:
1. 作为drawable
如果您将颜色定义为资源中的drawable而不是颜色(它可以在我们的colors.xml文件中):
<drawable name="sponsored_article_background">
或者
<drawable name="sponsored_article_background">@color/sponsored_article_background</drawable>
那么你应该能够像最初希望的那样使用android:background
,但需要提供可绘制对象而不是颜色:
android:background="@{article.sponsored ? @drawable/sponsored_article_background : null}"
这里的参数类型兼容:第一个是 Drawable
,第二个是 null,所以它也可以转换为 Drawable
。
2. 作为资源 ID
app:backgroundResource="@{article.sponsored ? R.color.sponsored_article_background : 0}"
但是这还需要在data
部分添加你的R类导入:
<data>
<import type="com.example.package.R" />
<variable ... />
</data>
将0作为“null资源ID”传递是安全的,因为View
的setBackgroundResource
方法会检查resid
是否与0不同,如果相同,则将null设置为背景可绘制对象。这样就不会创建不必要的透明可绘制对象。
public void setBackgroundResource(int resid) {
if (resid != 0 && resid == mBackgroundResource) {
return;
}
Drawable d= null;
if (resid != 0) {
d = mResources.getDrawable(resid);
}
setBackgroundDrawable(d);
mBackgroundResource = resid;
}