Wie verwende ich die Datenbindung, um eine Zeichenfolge aus Ressourcen mit einer dynamischen Variablen in XML zu kombinieren?

125

Ich habe eine Textansicht mit einer fest codierten Zeichenfolge und eine dynamische Variable, die ich am Ende dieser Zeichenfolge einfügen möchte. Das ist mein Code:

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

Ich habe ein Problem mit android:text="@string/Generic_Text"+"@{ Profile.name }". Der Generic_TextStatus "Mein Name ist" ist dann Profile.namedynamisch und ändert sich offensichtlich von Profil zu Profil. Ich möchte, dass die gesamte TextView-Ausgabe Mein Name ist {Profilname} . Jede Hilfe wäre großartig.

Ignacio Perez
quelle
Verwenden Sie die Datenbindung?
Malmling
Ja, ich benutze Datenbindung
Ignacio Perez
Fügen Sie bitte auch Ihren aktuellen Java-Code hinzu.
Malmling

Antworten:

160

Du kannst das:

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

Wenn Sie die Zeichenfolgenformatierung für Ihre Generic_TextZeichenfolge verwenden. Ex. %sAm Ende

C0D3LIC1OU5
quelle
Vielen Dank, ich habe das gerade eingegeben und es hat richtig funktioniert
Ignacio Perez
5
Dies sollte nicht die akzeptierte Antwort sein, da hierdurch keine Datenbindungsfunktionen zum Bearbeiten des Texts verwendet werden.
Darwind
1
stimme @Darwind zu, siehe meine Antwort für eine funktionierende Implementierung mit Binding Adapters
juanagui
@IgorGanapolsky Diese Antwort ist über 3 Jahre alt, hat aber definitiv früher funktioniert. Erinnerst du dich, was schief gelaufen ist, als du es versucht hast?
C0D3LIC1OU5
320

Sie können dies noch einfacher tun:

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

Ihre Zeichenfolge sollte folgendermaßen aussehen:

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

Bearbeiten:

  1. Natürlich können Sie so viele Variablen verwenden, wie Sie benötigen:

    android:text= "@{@string/generic_text(profile.firstName, profile.secondName)}"
    
    <string name="generic_text">My Name is %1$s %2$s</string>
  2. Es funktioniert nur, weil es für die Datenbindung ausgelegt ist. Weitere Informationen finden Sie in den Dokumenten: https://developer.android.com/topic/libraries/data-binding/expressions#resources

Roman_D
quelle
1
aber es zeigt, My Name is nullwenn Daten noch nicht bereit sind (z. B. nicht aus dem Netzwerk geladen wurden)
user924
1
In diesem Fall überprüfen Sie es einfach vorher. android:text= "@{profile == null ? @string/loading : @string/generic_text(profile.firstName, profile.secondName)}"
Roman_D
Das ist hilfreich!
Akash89
Die beste Antwort :)
Heriberto Rivera
55

Viele Möglichkeiten, um Saiten zu konzentrieren

1. Verwenden einer Zeichenfolgenressource ( Empfohlen wegen Lokalisierung )

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

Machen Sie einfach eine String-Ressource wie diese.

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

2. Hartcodierter Concat

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

Dies ist nützlich, wenn Sie einen fest codierten Anhang wie + für die Telefonnummer benötigen.

3. Verwenden Sie Stringdie Concat-Methode

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

Hier spaceist eine HTML-Entität, die im Inneren platziert wird strings.xml. Weil XMLkeine HTML-Entitäten oder Sonderzeichen direkt akzeptiert. (Link HTML Entities)

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

4. Verwenden von String.format()

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

Sie müssen die String-Klasse im Layout dieses Typs importieren.

<?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. Konzentrieren Sie zwei Zeichenfolgen nach Zeichenfolgenressourcen.

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

In diesem Fall fügen Sie eine Zeichenfolgenressource ein strings.xml

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

Es gibt viele andere Möglichkeiten, wählen Sie eine, die Sie benötigen.

Khemraj
quelle
5

Verwenden Sie einen Bindungsadapter .

Dieses Beispiel ist in Kotlin geschrieben und berücksichtigt, dass die gebundene Variable null sein kann:

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

Verwenden Sie dann den Bindungsadapter in Ihrem XML anstelle der android:textEigenschaft

app:my_name="@{Profile.name}"
Juanagui
quelle
Da ich große Probleme beim Aufrufen importierter Funktionen in der Bindung hatte, funktioniert diese Antwort perfekt für mich und ermöglicht mir, meine Erweiterungen wiederzuverwenden. Vielen Dank!
Danny Buonocore
Da die grundlegende Manipulation bereits von Stringclass from bereitgestellt wird xml, eignet sich diese Lösung nur für erweiterte String-Manipulationen, die Ihren Anforderungen entsprechen. Es ist jedoch nicht falsch.
sud007
3

2019 Update, Android Studio auf 3.4, Android Gradle Plugin auf 3.4

Zum Importieren nicht mehr erforderlich

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

für String-Operationen. Bitte überprüfen Sie diese Antwort .

SANAT
quelle
1

Falls Sie die Ressourcenzeichenfolge am Ende nicht ändern können%s (z. B. weil sie ohne das Suffix an anderer Stelle verwendet wird):

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

Wenn Profile.namenicht null sein kann, ist das genug. Wenn jedoch etwas nullpassiert, stürzt es ab. Sie müssen eine weitere Ebene hinzufügen:

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

(was erfordert, um <import type="java.util.Objects"/>zu arbeiten.)

Nochmals: All diese zusätzliche Arbeit lohnt sich nur, wenn Sie die Ressourcenzeichenfolge an anderer Stelle verwenden. Der zweite Grund ist, wenn Sie nullals "leere Zeichenfolge" anstelle eines "Null" -Literal behandeln möchten .

Agent_L
quelle
2
Wenn die Zeichenfolgenressource an anderer Stelle verwendet wird, warum nicht einfach eine neue Ressource erstellen?
Jarett Millard
0

Wenn Sie Text in XML eingeben möchten , können Sie ein Anführungszeichen verwenden.

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

An anderer Stelle müssen Sie sich mit dem String oder der Variablen auseinandersetzen , die Sie verwenden können

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

Wenn Sie anstelle der Variablen, die Sie ausführen können, eine String-String-Ressource verwenden möchten ,

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

Nur +Operator zu verwenden funktioniert für mich:

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

String.xml lautet:

<string name="Generic_Text">Hello</string>
Shalu TD
quelle