Reputation: 12521
Data binding in Android currently seems to support the following reference resources (according to data binding guide): @array
, @color
, @int
, @dimen
, @string
... which will give referenced values as arguments in static @BindingAdapter
method.
For example:
layout/web_view.xml
<WebView
app:htmlTextColor="@{@color/colorText}"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Bindings.java
@BindingAdapter({"bind:htmlTextColor"})
public static void setHtml(WebView webView, int textColor) {
// binding logic
}
But with themes and styles, it's more often that I use an attribute resource, e.g. ?android:attr/textColorPrimary
than a @color
reference. For such cases, how would the binding "@{}"
syntax look like? Currently this is how I make it work, but maybe there is a better way?
layout/web_view.xml
<WebView
app:htmlTextColor="@{android.R.attr.textColorPrimary}"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Bindings.java
@BindingAdapter({"bind:htmlTextColor"})
public static void setHtml(WebView webView, int textColorAttr) {
// binding logic
}
Upvotes: 36
Views: 8860
Reputation: 38223
If @{android.R.attr.textColorPrimary}
resolves to the value of android.R.attr.textColorPrimary
in Java, all you need to do is resolve that to a color.
There's a bit of a setup going into this.
The following method resolves supplied attr
of context
's theme and optional style
to a color. Falls back to fallback
color if there's an error.
@ColorInt
public static int resolveColor(final Context context, @StyleRes final int style, @AttrRes final int attr, @ColorInt final int fallback) {
final TypedArray ta = obtainTypedArray(context, style, attr);
try {
return ta.getColor(0, fallback);
} finally {
ta.recycle()
}
}
@ColorInt
public static int resolveColor(final Context context, @AttrRes final int attr, @ColorInt final int fallback) {
return resolveColor(context, 0, attr, fallback);
}
Utility methods helping to achieve the above goal efficiently.
private static TypedArray obtainTypedArray(final Context context, @StyleRes final int style, @AttrRes final int attr): TypedArray {
final int[] tempArray = getTempArray();
tempArray[0] = attr;
return context.obtainStyledAttributes(style, tempArray);
}
private static final ThreadLocal<int[]> TEMP_ARRAY = new ThreadLocal<>();
private static final int[] getTempArray() {
int[] tempArray = TEMP_ARRAY.get();
if (tempArray == null) {
tempArray = int[1];
TEMP_ARRAY.set(tempArray);
}
return tempArray;
}
More complex code available in my android-commons
library (here and here).
Here's how to use it:
@BindingAdapter({"bind:htmlTextColor"})
public static void setHtml(final WebView webView, @AttrRes final int textColorAttr) {
final Context context = webView.getContext();
final int textColor = ContextUtils.resolveColor(context, textColorAttr, Color.BLACK);
// binding logic
}
Upvotes: 2
Reputation: 11
Use a BindingAdapter
A BindingAdapter lets you manipulate and do a bit more involved logic on your data before applying it to the View. To use a BindingAdapter, first create a static method in your code that is bound to either a standard Android attribute or a custom one.
I create a custom attribute here called characterBackground:
@BindingAdapter({"characterBackground"})
public static void characterBackground(TextView textView, AdventureTimeCharacters character) {
textView.setBackgroundColor(ContextCompat.getColor(textView.getContext(), character.getColour()));
}
You can then use this BindingAdapter in the TextView:
app:characterBackground="@{character}"
Do not forget to add the app namespace! Android Studio can add this for you. Just type in appNs and it will autocomplete.
This solution works, but is a bit too involved. And you said data binding is easy..
Upvotes: 1
Reputation: 2195
It appears that themes are currently not supported for use in layout expressions with databinding as is explained by @yigit in the comments for the question here.
Upvotes: 0