データバインディングを使用して、リソースの文字列をXMLの動的変数と組み合わせるにはどうすればよいですか?


125

ハードコードされた文字列を持つTextViewがあり、この文字列の最後に配置する動的変数があります。これは私のコードです:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp">
    <TextView
        android:id="@+id/PeopleName"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/Generic_Text"+"@{ Profile.name }" />


</LinearLayout>

で問題が発生してい android:text="@string/Generic_Text"+"@{ Profile.name }"ます。Generic_Text「私の名前は」という状態Profile.nameは動的であり、明らかにプロファイル間で変化します。TextView出力全体がMy Name is {Profile.name}になるようにしたいです。どんな助けでも素晴らしいでしょう。


データバインディングを使用していますか?
malmling

はい、私はデータバインディングを使用しています
Ignacio Perez

現在のJavaコードも追加してください。
不正操作

回答:


162

あなたはこれを行うことができます:

android:text= "@{String.format(@string/Generic_Text, Profile.name)}"

文字列に文字列フォーマットを使用する場合Generic_Text。例。%s最後に


おかげで私はちょうどそれを入れて、それは正しく機能しました
Ignacio Perez

5
これは、実際にはデータバインディング機能を使用してテキストを操作しないため、受け入れられるべきではありません。
ダーウィンド

1
@Darwindに同意します。BindingAdaptersを使用した実装の動作については、私の回答を参照しください
juanagui

@IgorGanapolskyこの回答は3年以上前のものですが、以前は間違いなく機能していました。試したときに何が問題だったか覚えていますか?
C0D3LIC1OU5

320

あなたはこれをさらに簡単にすることができます:

android:text= "@{@string/generic_text(profile.name)}"

文字列は次のようになります。

<string name="generic_text">My Name is %s</string>

編集:

  1. もちろん、必要なだけ変数を使用できます。

    android:text= "@{@string/generic_text(profile.firstName, profile.secondName)}"
    
    <string name="generic_text">My Name is %1$s %2$s</string>
    
  2. データバインディングで設計されているという理由だけで機能します。ドキュメントの詳細:https : //developer.android.com/topic/libraries/data-binding/expressions#resources


1
しかしMy Name is null、データがまだ準備されていない(たとえば、ネットワークから読み込まれなかった)かどうかを示します
user924

1
この場合は、前に確認してください。android:text= "@{profile == null ? @string/loading : @string/generic_text(profile.firstName, profile.secondName)}"
Roman_D

これは役に立ちます!
akash89

ベストアンサー:)
Heriberto Rivera

55

文字列を連結する多くの方法

1.文字列リソースの使用(ローカライズのために推奨

android:text= "@{@string/generic_name(user.name)}"

このような文字列リソースを作成するだけです。

<string name="generic_name">Hello %s</string>

2.ハードコードされた連結

android:text="@{`Hello ` + user.name}"/>

これは、電話番号に+などのハードコードされた追加が必要な場合に役立ちます。

3. Stringのconcatメソッドの使用

android:text="@{user.firstName.concat(@string/space).concat(user.lastName)}"

ここでspaceの内部に配置されているHTMLエンティティがありますstrings.xmlXMLは、Htmlエンティティまたは特殊文字を直接受け入れないためです。(HTMLエンティティのリンク)

<string name="space">\u0020</string>

4.使用 String.format()

android:text= "@{String.format(@string/Hello, user.name)}"

このタイプのレイアウトでStringクラスをインポートする必要があります。

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <import type="String" />
    </data>
    <TextView
        android:text= "@{String.format(@string/Hello, user.name)}"
        ... >
    </TextView>
</layout>

5.文字列リソースによって2つの文字列を連結します。

android:text="@{@string/generic_name(user.firstName,user.lastName)}"

この場合、文字列リソースを strings.xml

<string name="generic_name">%1$s, %2$s</string>

他にも多くの方法があります。必要な方法を選択してください。


5

使用するバインディングアダプタ

このサンプルはKotlinで記述されており、バインドされた変数がnullになる可能性があることを考慮しています。

@BindingAdapter("my_name")
fun TextView.setMyName(name: String?) {
    this.text =
        if (name.isNullOrEmpty()) "" else "${this.context.getString(R.string.Generic_Text)} $name"
}

次に、android:textプロパティの代わりにXMLでバインディングアダプターを使用します

app:my_name="@{Profile.name}"

バインディングでインポートされた関数を呼び出すのに多くの問題がありましたが、この答えは私にとって完璧に機能し、拡張機能を再利用することができます。ありがとう!
Danny Buonocore

基本的な操作はのStringクラスによってすでに提供されているためxml、このソリューションは、要件に基づく高度な文字列操作にのみ使用できます。ただし、これは間違いではありません。
sud007

3

2019アップデート、Androidスタジオから3.4、Android Gradleプラグインから3.4

インポートする必要はありません

<import type="java.lang.String" />" 

文字列操作用。この回答を確認してください。


1

最後に含めるようにリソース文字列を変更できない場合%s(たとえば、サフィックスなしで他の場所で使用されているため):

android:text="@{@string/Generic_Text.concat(Profile.name)}"

Profile.namenullにできない場合はそれで十分です。ただし、a nullが発生すると、クラッシュします。別のレイヤーを追加する必要があります:

android:text="@{@string/Generic_Text.concat(Objects.toString(Profile.name))}"

(動作する必要があり<import type="java.util.Objects"/>ます。)

繰り返しますが、この余分な作業はすべて、他の場所で使用されているリソース文字列がある場合にのみ価値があります。2番目の理由はnull、「null」リテラルではなく「空の文字列」として処理する場合です。


2
文字列リソースが他の場所で使用されている場合、なぜ新しいリソースを作成しないのですか?
Jarett Millard、2018

0

あなたがしたい場合は場合は、テキスト入力 XML内には、使用することができます``引用を。

android:text="@{`Device Name`}"

あなたが文字列または変数連結する必要がある他の場所では、あなたは使うことができます

android:text="@{`Device Name`.concat(android.os.Build.MANUFACTURER)}"

あなたができる変数の代わりに文字列リソース連結したいなら、

android:text="@{@string/app_name.concat(`Device Name`)}"

0

+演算子を使用するだけでうまくいきます:

android:text= "@{@string/Generic_Text +' '+ Profile.name)}"

String.xmlは次のようになります。

<string name="Generic_Text">Hello</string>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.