使用DataBinding库设置背景颜色资源或null

我想使用DataBinding库在我的视图设置背景颜色或null ,但我得到一个异常,试图运行它。

 java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference 

这是我如何做到的:

 android:background="@{article.sponsored ? @color/sponsored_article_background : null}" 

我也尝试设置转换,但没有奏效。

 @BindingConversion public static ColorDrawable convertColorToDrawable(int color) { return new ColorDrawable(color); } 

最终,我用@BindingAdapter解决方法解决了它,但我想知道如何正确地做到这一点。

原因:

首先要知道的是,DataBinding库已经提供了位于android.databinding.adapters.Converters.convertColorToDrawable(int)convertColorToDrawable绑定转换器。

使用android:background应该“理论上”工作,因为它有一个相应的setBackground(Drawable)方法。 问题是,它看到你尝试传递一个颜色作为第一个参数,所以它试图启动这个转换器,然后将其应用于setBackground(Drawable)方法。 如果数据绑定决定使用一个转换器,它将在两个参数上使用它,所以在null ,就在将最终结果应用于setter之前。
由于null不能为int (并且不能调用intValue() ,所以它会抛出NullPointerException异常。

官方的“ 数据绑定指南”不支持混合参数类型。

这里有两个解决这个问题的方法。 虽然您可以使用这两种解决方案中的任何一种,但第一种解决方案更容易。

解决方案:

1.可绘制

如果您不是将颜色定义为颜色,而是将其定义为资源中的drawable(可以在我们的colors.xml文件中:

 <drawable name="sponsored_article_background">#your_color</drawable> 

要么

 <drawable name="sponsored_article_background">@color/sponsored_article_background</drawable> 

那么你应该能够使用android:background像你最初想要的,但提供drawable而不是颜色:

 android:background="@{article.sponsored ? @drawable/sponsored_article_background : null}" 

这里的参数具有兼容的类型:第一个是Drawable ,第二个是null,所以它也可以转换为Drawable

2.作为资源ID

 app:backgroundResource="@{article.sponsored ? R.color.sponsored_article_background : 0}" 

但它也将需要添加您的R类导入data部分:

 <data> <import type="com.example.package.R" /> <variable ... /> </data> 

将0作为“空资源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; } 

我认为你必须尝试默认color而不是null

喜欢这个

 android:background="@{article.sponsored ? @color/sponsored_article_background : @color/your_default_color}" 

你可以使用的一种方法是编写一个自定义的@BindingConversion来为你处理:

 @BindingConversion public static ColorDrawable convertColorToDrawable(int color) { return color != 0 ? new ColorDrawable(color) : null; } 

有了这个,你可以将任何接受ColorDrawable属性设置为一个整数颜色值(比如0或@android:color/transparent ),并自动将它转换为轻量级的@null。

(而内置的convertColorToDrawable(int)转换器总是创建一个ColorDrawable对象,即使颜色是透明的。)

注意:为了使用这个方法代替内置的@BindingConversion ,它必须返回一个ColorDrawable而不是一个Drawable ,否则内置的方法将被视为更具体/合适。


另一种方法是在数据绑定表达式中使用静态方法将颜色转换为Drawable ,以使值类型匹配。 例如,您可以导入内置的Converters类:

 <data> <import type="android.databinding.adapters.Converters"/> </data> 

…并写下你的表情:

 android:background="@{article.sponsored ? Converters.convertColorToDrawable(@color/sponsored_article_background) : null}" 

…虽然我个人建议将这种条件逻辑放在数据绑定适配器方法中,例如使用返回Drawable或null的getArticleBackground()方法。 一般情况下,如果避免在布局文件中放置决策逻辑,则更易于调试和跟踪。

尝试这个:

 @Bindable private int color; 

和构造函数中

 color = Color.parseColor("your color in String for examp.(#ffffff)") 

在xml中:

 android:textColor = "@{data.color}" 

你可以使用@BindingAdapter(“android:background”)并设置任何资源。

如果你正在写Kotlin – 只是复制粘贴到你的项目: https : //github.com/OlegTarashkevich / ObservableBackground