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
でも両方の引数で使用します。null
をint
にキャストできないため(そして、その上で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を渡すと、setBackgroundResource
のView
メソッドが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}"
使用できる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()
メソッドを使用します。一般に、レイアウトファイル内に決定ロジックを配置しないようにすれば、デバッグや追跡が容易になります。
これを試して:
@Bindable
private int color;
およびコンストラクター内
color = Color.parseColor("your color in String for examp.(#ffffff)")
xmlで:
Android:textColor = "@{data.color}"
この 記事 では、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}" />