Come si utilizza l'associazione dati per combinare una stringa dalle risorse con una variabile dinamica in XML?


125

Ho un TextView che ha una stringa hardcoded e ho una variabile dinamica che voglio mettere alla fine di questa stringa. Questo è il mio codice:

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

Ho un problema con android:text="@string/Generic_Text"+"@{ Profile.name }". La Generic_Textdicitura "Il mio nome è" quindi Profile.nameè dinamica e ovviamente cambia da profilo a profilo. Lo voglio in modo che l'intero output di TextView sia Il mio nome è {Profile.name} . Qualsiasi aiuto sarebbe grande.


Stai usando l'associazione dati?
malmling

Sì, sto usando l'associazione dati
Ignacio Perez

Aggiungi anche il tuo attuale codice java per favore.
malmling

Risposte:


162

Puoi farlo:

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

se usi la formattazione della stringa per la tua Generic_Textstringa. ex. %salla fine


Grazie mille, l'ho appena inserito e ha funzionato correttamente
Ignacio Perez

5
Questa non dovrebbe essere la risposta accettata, poiché in realtà non utilizza le funzionalità di associazione dati per manipolare il testo.
Darwind

1
d'accordo con @Darwind, vedere la mia risposta per un'implementazione funzionante con Binding Adapters
juanagui

@IgorGanapolsky questa risposta ha più di 3 anni ma sicuramente funzionava prima - ricordi cosa è andato storto quando l'hai provato?
C0D3LIC1OU5

320

Puoi farlo in modo ancora più semplice:

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

la tua stringa dovrebbe essere così:

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

Modificare:

  1. Ovviamente puoi usare tutte le variabili di cui hai bisogno:

    android:text= "@{@string/generic_text(profile.firstName, profile.secondName)}"
    
    <string name="generic_text">My Name is %1$s %2$s</string>
  2. Funziona solo perché è progettato nel data binding. Maggiori informazioni nei documenti: https://developer.android.com/topic/libraries/data-binding/expressions#resources


1
ma mostra My Name is nullse i dati non sono ancora pronti (ad esempio, non sono stati caricati dalla rete)
user924

1
In questo caso basta controllarlo prima. android:text= "@{profile == null ? @string/loading : @string/generic_text(profile.firstName, profile.secondName)}"
Roman_D

Questo è utile!
akash89

La migliore risposta :)
Heriberto Rivera

55

Molti modi per concatenare le stringhe

1. Utilizzo della risorsa stringa ( consigliato perché localizzazione )

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

Crea solo una risorsa stringa come questa.

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

2. Concat. Hard coded

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

Questo è utile quando hai bisogno di aggiungere hardcoded come + per il numero di telefono.

3. Utilizzo Stringdel metodo concat di

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

Ecco spaceun'entità html che si trova all'interno strings.xml. PerchéXML non accetta direttamente entità Html o caratteri speciali. (Collega entità HTML)

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

4. Utilizzando String.format()

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

devi importare la classe String nel layout di questo tipo.

<?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. concatenare due stringhe per risorsa stringa.

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

In questo caso inserisci una risorsa stringa strings.xml

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

Ci possono essere molti altri modi, scegli quello che ti serve.


5

Utilizzare un adattatore di rilegatura .

Questo esempio è scritto in Kotlin e tiene conto del fatto che la variabile associata può essere nulla:

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

quindi usa l'adattatore di binding nel tuo XML invece della android:textproprietà

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

Ho avuto molti problemi a chiamare le funzioni importate nell'associazione, questa risposta funziona perfettamente per me e mi consente di riutilizzare le mie estensioni. Grazie!
Danny Buonocore

Poiché la manipolazione di base è già fornita dalla Stringclasse from xml, questa soluzione è valida solo per essere utilizzata per manipolazioni avanzate di stringhe in base alle proprie esigenze. Tuttavia, non è corretto.
sud007

3

Aggiornamento 2019, Android Studio a 3.4, Plugin Android Gradle a 3.4

Non è più necessario importare

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

per operazioni su stringhe. Si prega di controllare questa risposta .


1

Nel caso in cui non sia possibile modificare la stringa della risorsa in modo che contenga %salla fine (ad esempio perché è usata altrove senza il suffisso):

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

Se Profile.namenon può essere nullo, è sufficiente. Tuttavia, se nullsuccede, andrà in crash. Devi aggiungere un altro livello:

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

(che richiede <import type="java.util.Objects"/>di funzionare.)

Di nuovo: tutto questo lavoro extra vale la pena solo se hai la stringa della risorsa usata altrove. Il secondo motivo è quando si desidera gestire nullcome "stringa vuota" invece di un valore letterale "null".


2
Se la risorsa stringa viene utilizzata altrove, perché non creare semplicemente una nuova risorsa?
Jarett Millard

0

Nel caso in cui desideri digitare del testo in XML, puoi usare `` citazione.

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

altrove è necessario concatenare con la stringa o la variabile , è possibile utilizzare

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

se vuoi concatenare la risorsa stringa invece della variabile puoi fare,

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

0

Il solo utilizzo +dell'operatore funziona per me:

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

String.xml sarà:

<string name="Generic_Text">Hello</string>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.