Ist es möglich, String.xml in Android dynamisch hinzuzufügen?

495

Ist es möglich, Platzhalter in Zeichenfolgenwerten zu haben string.xml, denen zur Laufzeit Werte zugewiesen werden können?

Beispiel:

einige Zeichenfolge PLACEHOLDER1 einige weitere Zeichenfolge

SoftReference
quelle
@ HarishGyanani Nein, dieser ist älter, dass man stattdessen mit diesem zusammengeführt werden sollte
Danh

Antworten:

1035

Formatierung und Styling

Ja, siehe Folgendes unter Zeichenfolgenressourcen: Formatieren und Stylen

Wenn Sie Ihre Zeichenfolgen mit formatieren müssen, String.format(String, Object...)können Sie dies tun, indem Sie Ihre Formatargumente in die Zeichenfolgenressource einfügen. Zum Beispiel mit der folgenden Ressource:

<string name="welcome_messages">Hello, %1$s! You have %2$d new messages.</string>

In diesem Beispiel hat die Formatzeichenfolge zwei Argumente: %1$sist eine Zeichenfolge und %2$deine Dezimalzahl. Sie können die Zeichenfolge mit Argumenten aus Ihrer Anwendung wie folgt formatieren:

Resources res = getResources();
String text = String.format(res.getString(R.string.welcome_messages), username, mailCount);

Grundlegende Verwendung

Beachten Sie, dass getStringes eine Überladung gibt, die die Zeichenfolge als Formatzeichenfolge verwendet:

String text = res.getString(R.string.welcome_messages, username, mailCount);

Pluralformen

Wenn Sie mit Pluralformen umgehen müssen, verwenden Sie Folgendes:

<plurals name="welcome_messages">
    <item quantity="one">Hello, %1$s! You have a new message.</item>
    <item quantity="other">Hello, %1$s! You have %2$d new messages.</item>
</plurals>

Der erste mailCountParameter wird verwendet, um zu entscheiden, welches Format verwendet werden soll (Einzel- oder Plural). Die anderen Parameter sind Ihre Ersetzungen:

Resources res = getResources();
String text = res.getQuantityString(R.plurals.welcome_messages, mailCount, username, mailCount);

Siehe String - Ressourcen: Plurale für weitere Details.

Megha Joshi - GoogleTV DevRel
quelle
61
Der Aufruf von String.format im ersten Codebeispiel ist eigentlich nicht erforderlich. Resources.getString () unterstützt die Formatierung, siehe: developer.android.com/reference/android/content/res/… , java.lang.Object ...)
Arnaud
16
Für Plurals in String.xml müssen Sie die ID als R.plurals.welcome_messages anstelle von R.string.welcome_messages angeben
om252345
Plural Ding, das nur die letzte Elementzeichenfolge zurückgibt ... jede Idee, wie man eine Zeichenfolge anhängen kann.
CoDe
1
Bei Verwendung dieser Methode zum Formatieren Ihrer Zeichenfolge wurden alle Meta-Tags entfernt, die Sie möglicherweise verwendet haben, z. B. Hyperlinks usw., die im XML-Zeichenfolgentext enthalten sein könnten
Jonathan
4
String steht für% 1 $ s, Dezimalzahl für% 2 $ d und Integer steht für was? Was bedeutet% 1,% 2.Ist diese Parameterzählung? .wenn ich den dritten Parameter möchte, wird% 3 erwähnt?
reegan29
260

Ergänzende Antwort

Als ich das erste Mal sah %1$sund %2$din der akzeptierten Antwort, machte es keinen Sinn. Hier ist eine weitere Erklärung.

Sie werden als Formatbezeichner bezeichnet. In der XML-Zeichenfolge haben sie die Form

%[parameter_index$][format_type] 
  • % : Das Prozentzeichen markiert den Beginn des Formatbezeichners.
  • Parameterindex : Dies ist eine Zahl, gefolgt von einem Dollarzeichen. Wenn Sie drei Parameter haben , die Sie in die String einfügen wollten, dann würden sie genannt werden 1$, 2$und 3$. Die Reihenfolge, in der Sie sie in die Ressourcenzeichenfolge einfügen, spielt keine Rolle, nur die Reihenfolge, in der Sie die Parameter angeben.
  • Formattyp : Es gibt viele Möglichkeiten, wie Sie Dinge formatieren können ( siehe Dokumentation ). Hier sind einige gebräuchliche:

    • s Zeichenfolge
    • d Dezimalzahl
    • f Gleitkommazahl

Beispiel

Wir werden die folgende formatierte Zeichenfolge erstellen, in die die grauen Teile programmgesteuert eingefügt werden.

Meine Schwester Maryist 12Jahre alt.

string.xml

<string name="my_xml_string">My sister %1$s is %2$d years old.</string>

MyActivity.java

String myString = "Mary";
int myInt = 12;
String formatted = getString(R.string.my_xml_string, myString, myInt);

Anmerkungen

  • Ich konnte verwenden, getStringweil ich in einer Aktivität war. Sie können verwenden, context.getResources().getString(...)wenn es nicht verfügbar ist.
  • String.format() formatiert auch einen String.
  • Die Begriffe 1$und 2$müssen nicht in dieser Reihenfolge verwendet werden. Das heißt, 2$kann vorher kommen 1$. Dies ist nützlich, wenn Sie eine App für Sprachen internationalisieren, die eine andere Wortreihenfolge verwenden.
  • Sie können einen Formatbezeichner wie %1$smehrmals in der XML verwenden, wenn Sie ihn wiederholen möchten.
  • Verwenden Sie %%, um den tatsächlichen %Charakter zu erhalten.
  • Weitere Informationen finden Sie im folgenden hilfreichen Tutorial: Android SDK-Kurztipp: Formatieren von Ressourcenzeichenfolgen
Suragch
quelle
125

Wenn Sie einen Parameter aus der eigentlichen Datei strings.xml verwenden möchten, ohne Java-Code zu verwenden:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE resources [
  <!ENTITY appname "WhereDat">
  <!ENTITY author "Oded">
]>

<resources>
    <string name="app_name">&appname;</string>
    <string name="description">The &appname; app was created by &author;</string>
</resources>

Dies funktioniert nicht über Ressourcendateien hinweg, dh Variablen müssen in jede XML-Datei kopiert werden, die sie benötigt.

Oded Breiner
quelle
Das ist eine gute Antwort, außer wenn Sie einen Parameter in <! [CDATA [& param; ]]>
Hermann Poilpre
2
Gibt es eine Möglichkeit, das <!DOCTYPE... ]>Teil in einer separaten Datei zu definieren und in mehrere Ressourcendateien aufzunehmen? Irgendein Trick, um dies zu erreichen?
prom85
18

War auf der Suche nach dem gleichen und fand schließlich die folgende sehr einfache Lösung. Das Beste: Es funktioniert sofort.
1. Ändern Sie Ihre String-Ressource:

<string name="welcome_messages">Hello, <xliff:g name="name">%s</xliff:g>! You have 
<xliff:g name="count">%d</xliff:g> new messages.</string>

2. Verwenden Sie die Zeichenfolgenersetzung:

c.getString(R.string.welcome_messages,name,count);

Dabei ist c der Kontext, name eine Zeichenfolgenvariable und zählt Ihre int-Variable

Sie müssen einschließen

<resources xmlns:xliff="http://schemas.android.com/apk/res-auto">

in Ihrer res / strings.xml. Funktioniert bei mir. :) :)

user3016503
quelle
2
Was ist der Sinn der xliffTags um die Formatspezifizierer? Welchen zusätzlichen Wert bieten sie im Gegensatz zur alleinigen Verwendung der %sund %d-Spezifizierer?
Richard Le Mesurier
Das Attribut "name" im xliff-Tag ist nur eine Möglichkeit, dem Übersetzer einen Hinweis darauf zu geben, was dort ersetzt wird. Manchmal ist es nicht leicht zu erraten, was "% s" bedeutet.
Hugomg
3

In Kotlin müssen Sie Ihren String-Wert nur so einstellen:

<string name="song_number_and_title">"%1$d ~ %2$s"</string>

Erstellen Sie eine Textansicht in Ihrem Layout:

<TextView android:id="@+id/song_number_and_title"/>

Dann tun Sie dies in Ihrem Code, wenn Sie Anko verwenden:

val song = database.use { // get your song from the database }
song_number_and_title.setText(resources.getString(R.string.song_number_and_title, song.number, song.title))  

Möglicherweise müssen Sie Ihre Ressourcen aus dem Anwendungskontext abrufen.

msbodw001
quelle
5
Wie unterscheidet sich das von Java-Beispielen? Ich sehe keinen Unterschied
Janusz Hain
1

in res / values ​​/ string.xml

<resources>
    <string name="app_name">Hello World</string>
    <string name="my_application">Application name: %s, package name: %s</string>
</resources>

in Java-Code

String[] args = new String[2];
args[0] = context.getString(R.string.app_name);
args[1] = context.getPackageName();
String textMessage = context.getString(R.string.my_application,(Object[]) args);
Chanh
quelle
1

Wenn Sie Prozent (%) schreiben möchten, duplizieren Sie es:

<string name="percent">%1$d%%</string>

label.text = getString(R.string.percent, 75) // Output: 75%.

Wenn Sie einfach schreiben %1$d%, erhalten Sie die Fehlermeldung : Format string 'percent' is not a valid format string so it should not be passed to String.format.

CoolMind
quelle
0

Ja! Sie können dies tun, ohne Java / Kotlin-Code zu schreiben, sondern nur XML, indem Sie diese kleine Bibliothek verwenden, die ich erstellt habe. Dies geschieht zur Erstellungszeit, sodass Ihre App davon nicht betroffen ist: https://github.com/LikeTheSalad/android -string-Referenz

Verwendungszweck

Deine Saiten:

<resources>
    <string name="app_name">My App Name</string>
    <string name="template_welcome_message">Welcome to ${app_name}</string>
</resources>

Die generierte Zeichenfolge nach dem Erstellen:

<!--resolved.xml-->
<resources>
    <string name="welcome_message">Welcome to My App Name</string>
</resources>
César Muñoz
quelle
0

Eine direkte Kotlin-Lösung für das Problem:

string.xml

<string name="customer_message">Hello, %1$s!\nYou have %2$d Products in your cart.</string>

kotlinActivityORFragmentFile.kt:

val username = "Andrew"
val products = 1000
val text: String = String.format(
      resources.getString(R.string.customer_message), username, products )
Nyxee
quelle
0

Verwenden Sie dies in Ihrer String-Datei

<string name="redeem_point"> You currently have %s points(%s points = 1 %s)</string>

Und in Ihrem Code entsprechend verwenden

coinsTextTV.setText(String.format(getContext().getString(R.string.redeem_point), rewardPoints.getReward_points()
                        , rewardPoints.getConversion_rate(), getString(R.string.rs)));
Soni Kumar
quelle
-1

Kotlin-Version der akzeptierten Antwort ...

val res = resources
val text = String.format(res.getString(R.string.welcome_messages), username, mailCount)
jesses.co.tt
quelle
3
Richtiger ist die Verwendung einer resources.getString(int, ... args)Methode mit Argumenten anstelle von String.format. Dieser Code enthält auch keine Kotlin-Details, außer dem valSchlüsselwort. Siehe Antwort von msbodw001
dant3