Use DataBinding library to set background color resource or null
I think you have to try default color
instead of null
like this
android:background="@{article.sponsored ? @color/sponsored_article_background : @color/your_default_color}"
Reason:
First thing to know is that DataBinding library already provides a convertColorToDrawable
binding converter located in android.databinding.adapters.Converters.convertColorToDrawable(int)
.
Using android:background
should "theoretically" work, because it has a corresponding setBackground(Drawable)
method. The problem is that it sees that you try to pass a color as a first argument so it tried to launch this converter before applying it to setBackground(Drawable)
method. If databinding decides to use a converter it will use it on both arguments, so also on null
, right before applying a final result to a setter.
Because null
cannot be castes to int
(and you cannot invoke intValue()
on it) it throws NullPointerException
.
There is a mention about the fact that mixed argument types are not supported in official Data Binding Guide.
Here are two solutions for this problem. Although you can use any of these two solutions, the first one is much easier.
Solutions:
1. As drawable
If you define your color not as a color but as a drawable in your resources (it can be in our colors.xml file:
<drawable name="sponsored_article_background">#your_color</drawable>
or
<drawable name="sponsored_article_background">@color/sponsored_article_background</drawable>
then you should be able to use android:background
like you originally wanted to but providing drawable instead of color:
android:background="@{article.sponsored ? @drawable/sponsored_article_background : null}"
Here arguments has compatible types: first is Drawable
and second is null so it can also be cast to a Drawable
.
2. As resource id
app:backgroundResource="@{article.sponsored ? R.color.sponsored_article_background : 0}"
but it will also require to add your R class import in data
section:
<data>
<import type="com.example.package.R" />
<variable ... />
</data>
Passing 0 as a "null resource id" is safe because setBackgroundResource
method of View
checks whether resid
is different than 0 and sets null as a background drawable otherwise. No unnecessary transparent drawable objects are created there.
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;
}
One approach you can use is to write a custom @BindingConversion
to take care of this for you:
@BindingConversion
public static ColorDrawable convertColorToDrawable(int color) {
return color != 0 ? new ColorDrawable(color) : null;
}
With this, you can set any attribute that accepts a ColorDrawable
to an integer color value (like 0 or @android:color/transparent
) and have it automatically converted to the lightweight @null for you.
(Whereas the built-in convertColorToDrawable(int)
convertor always creates a ColorDrawable
object, even if the color is transparent.)
Note: in order for this method to be used in place of the built-in @BindingConversion
, it must return a ColorDrawable
and not a Drawable
-- otherwise the built-in method will be seen as more specific/appropriate.
Another approach is to use a static method to convert from a color to a Drawable
within your data binding expression, in order to make the value types match. For example, you could import the built-in Converters
class:
<data>
<import type="androidx.databinding.adapters.Converters"/>
</data>
...and write your expression like this:
android:background="@{article.sponsored ? Converters.convertColorToDrawable(@color/sponsored_article_background) : null}"
...although I would personally recommend putting this kind of conditional logic in your data binding adapter method instead, e.g. using a getArticleBackground()
method that returns a Drawable or null. In general things are easier to debug and keep track of if you avoid putting decision logic within your layout files.
Try this:
@Bindable
private int color;
and in constructor
color = Color.parseColor("your color in String for examp.(#ffffff)")
in xml:
android:textColor = "@{data.color}"