web-dev-qa-db-ja.com

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を使用して回避策で解決しましたが、適切に行う方法を知りたいです。

31
Damian Petla

理由:

最初に知っておくべきことは、DataBindingライブラリが既にAndroid.databinding.adapters.Converters.convertColorToDrawable(int)にあるconvertColorToDrawableバインディングコンバーターを提供していることです。

_Android:background_を使用すると、対応する setBackground(Drawable) メソッドがあるため、「理論的に」機能するはずです。問題は、setBackground(Drawable)メソッドに適用する前にこのコンバーターを起動しようとしたため、色を最初の引数として渡そうとしていることです。データバインディングがコンバーターを使用することを決定した場合、最終結果をセッターに適用する直前に、nullでも両方の引数で使用します。
nullintにキャストできないため(そして、その上でintValue()を呼び出すことはできません)、NullPointerExceptionをスローします。

公式の Data Binding Guide では、混合引数タイプがサポートされていないという事実について言及されています。

この問題の解決策は2つあります。これら2つのソリューションのいずれも使用できますが、最初のソリューションの方がはるかに簡単です。

ソリューション:

1。描画可能として

あなたの色をリソースではなく、リソース内のドロウアブルとして定義する場合(colors.xmlファイルにあります:

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

または

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

それから、元々望んでいたように_Android:background_を使用できるはずですが、色の代わりにドロウアブルを提供します:

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

ここで、引数には互換性のある型があります。最初はDrawableで、2番目は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>
_

「nullリソースID」として0を渡すと、setBackgroundResourceViewメソッドが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;
}
_
61

colorの代わりにデフォルトのnullを試す必要があると思います

このような

Android:background="@{article.sponsored ? @color/sponsored_article_background : @color/your_default_color}"
9
pRaNaY

使用できる1つの方法は、カスタム_@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()メソッドを使用します。一般に、レイアウトファイル内に決定ロジックを配置しないようにすれば、デバッグや追跡が容易になります。

7
Lorne Laliberte

これを試して:

@Bindable
private int color;

およびコンストラクター内

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

xmlで:

Android:textColor = "@{data.color}"
1
C. Alen

この 記事 では、2つの良い解決策を見つけることができますが、私の場合は、マテリアルボタンの背景の色合いを変更したかったので、1つしか動作しません。

まず、Kotlinファイルを作成し、このアダプターメソッドを貼り付けます。

package com.nyp.kartak.utilities

import Android.content.res.ColorStateList
import androidx.databinding.BindingAdapter
import com.google.Android.material.button.MaterialButton
import com.nyp.kartak.model.ReceiptUserPurchaseModel

@BindingAdapter("backgroundTintBinding")
fun backgroundTintBinding(button: MaterialButton, model: ReceiptUserPurchaseModel) {
    button.backgroundTintList = ColorStateList.valueOf(button.resources.getColor( model.color))
}

次に、xmlで使用します。

<data>
    <variable
        name="model"
        type="com.nyp.kartak.model.ReceiptUserPurchaseModel" />
</data>

// .....

    <com.google.Android.material.button.MaterialButton
        Android:id="@+id/payBtn"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:text="@{model.getAction()}"
        app:backgroundTintBinding="@{model}" />
0