web-dev-qa-db-ja.com

レイアウトバインディングで属性リソース(?attr /)を使用していますか?

Androidのデータバインディングは現在、次の参照リソースをサポートしているようです( データバインディングガイド による):@array@color@int@dimen@string...これは、静的@BindingAdapterメソッドの引数として参照値を提供します。

例えば:

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
}

しかし、 テーマとスタイル の場合、属性リソースを使用することがよくあります。 ?android:attr/textColorPrimary参照よりも@color。このような場合、バインディング"@{}"構文はどのようになりますか?現在、これは私がそれを機能させる方法ですが、おそらくもっと良い方法がありますか?

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
}
27
hidro

Javaで@{Android.R.attr.textColorPrimary}Android.R.attr.textColorPrimaryの値に解決される場合、あなたがする必要があるのはそれを色に解決することだけです。

これには少し設定があります。

ContextUtils.Java

次のメソッドは、提供されたattrのテーマのcontextとオプションのstyleを色に解決します。エラーが発生した場合は、fallback色にフォールバックします。

@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);
}

上記の目標を効率的に達成するのに役立つユーティリティメソッド。

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;
}

my Android-commons library で利用可能なより複雑なコード(この部分はKotlinで記述されており、必要なものを使用してください)。

Bindings.Java

使用方法は次のとおりです。

@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
}
1
Eugen Pechanec

BindingAdapterを使用する

BindingAdapter を使用すると、データをビューに適用する前に、データを操作して、もう少し複雑なロジックを実行できます。 BindingAdapter を使用するには、最初に、標準のAndroid属性またはカスタム属性のいずれかにバインドされる静的メソッドをコードに作成します。

ここでcharacterBackgroundというカスタム属性を作成します。

@BindingAdapter({"characterBackground"})
public static void characterBackground(TextView textView, AdventureTimeCharacters character) {
     textView.setBackgroundColor(ContextCompat.getColor(textView.getContext(), character.getColour()));
}

その後、TextViewでこのBindingAdapterを使用できます。

app:characterBackground="@{character}"

アプリの名前空間を追加することを忘れないでください! Android Studioがこれを追加できます。appNsと入力するだけでオートコンプリートされます。

このソリューションは機能しますが、少し複雑すぎます。そして、データバインディングは簡単だとおっしゃいました。

1
Wilson S

質問のコメントで@yigitが説明しているように、テーマは現在、データバインディングを使用したレイアウト式での使用がサポートされていないようです ここ

0
SeptimusX75