¿Es posible agregar dinámicamente String a String.xml en Android?

Respuestas:

1036

Formateo y estilo

Sí, consulte lo siguiente en Recursos de cadena: formato y estilo

Si necesita formatear sus cadenas usando String.format(String, Object...), entonces puede hacerlo colocando sus argumentos de formato en el recurso de cadena. Por ejemplo, con el siguiente recurso:

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

En este ejemplo, la cadena de formato tiene dos argumentos: %1$ses una cadena y %2$des un número decimal. Puede formatear la cadena con argumentos de su aplicación de esta manera:

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

Uso básico

Tenga en cuenta que getStringtiene una sobrecarga que usa la cadena como una cadena de formato:

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

Plurales

Si necesita manejar plurales, use esto:

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

El primer mailCountparámetro se usa para decidir qué formato usar (simple o plural), los otros parámetros son sus sustituciones:

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

Ver Recursos de cadena: Plurales para más detalles.

Megha Joshi - GoogleTV DevRel
fuente
61
La llamada String.format en el primer ejemplo de código en realidad no es necesaria, Resources.getString () admite el formateo, consulte: developer.android.com/reference/android/content/res/… , java.lang.Object ...)
Arnaud
16
para Plurals en String.xml, debe proporcionar id como R.plurals.welcome_messages en lugar de R.string.welcome_messages
om252345
cosa plural que devuelve solo la última cadena de elementos ... alguna idea de cómo se puede agregar una cadena.
Código
1
Al usar este método para formatear su cadena, eliminó cualquier metaetiqueta que haya usado, como hipervínculos, etc., que podría haber estado contenida en el texto de la cadena xml
Jonathan
44
Cadena significa% 1 $ s, decimal para% 2 $ d y entero significa ¿qué? ¿Cuál es el significado% 1,% 2. ¿Es este recuento de parámetros? .si quiero el tercer parámetro ¿Se menciona% 3?
reegan29
260

Respuesta suplementaria

Cuando vi por primera vez %1$sy %2$den la respuesta aceptada, no tenía sentido. Aquí hay un poco más de explicación.

Se llaman especificadores de formato. En la cadena xml están en forma de

%[parameter_index$][format_type] 
  • % : El signo de porcentaje marca el comienzo del especificador de formato.
  • índice de parámetro : este es un número seguido de un signo de dólar. Si usted tenía tres parámetros que se desea introducir en la cadena, entonces estarían llamada 1$, 2$y 3$. No importa el orden en que los coloque en la cadena de recursos, solo el orden en que proporciona los parámetros.
  • tipo de formato : hay muchas formas de formatear las cosas ( consulte la documentación ). Aquí hay algunos comunes:

    • s cuerda
    • d entero decimal
    • f número de coma flotante

Ejemplo

Crearemos la siguiente cadena formateada donde las partes grises se insertan mediante programación.

Mi hermana Marytiene 12años

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

Notas

  • Podría usar getStringporque estaba en una Actividad. Puedes usarcontext.getResources().getString(...) si no está disponible.
  • String.format() también formateará una cadena.
  • El 1$y 2$términos no necesita ser utilizado en ese orden. Es decir, 2$puede venir antes 1$. Esto es útil al internacionalizar una aplicación para idiomas que usan un orden de palabras diferente.
  • Puede usar un especificador de formato como %1$svarias veces en el xml si desea repetirlo.
  • Use %%para obtener el %personaje real .
  • Para obtener más información, lea el siguiente tutorial útil: Consejo rápido del SDK de Android: formateo de cadenas de recursos
Suragch
fuente
125

Cuando desee utilizar un parámetro del archivo strings.xml real sin utilizar ningún código Java:

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

Esto no funciona en todos los archivos de recursos, es decir, las variables deben copiarse en cada archivo XML que las necesite.

Oded Breiner
fuente
Esa es una buena respuesta, excepto cuando tiene un parámetro dentro de <! [CDATA [& param; ]]>
Hermann Poilpre
2
¿Hay alguna forma de definir la <!DOCTYPE... ]>parte en un archivo separado e incluirlo en múltiples archivos de recursos? ¿Algún truco para lograr esto?
prom85
18

Estaba buscando lo mismo y finalmente encontré la siguiente solución muy simple. Lo mejor: funciona fuera de la caja.
1. altere su recurso de cadena:

<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. usar sustitución de cadena:

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

donde c es el contexto, el nombre es una variable de cadena y cuenta su variable int

Tendrás que incluir

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

en su res / strings.xml. Funciona para mi. :)

usuario3016503
fuente
2
¿Cuál es el punto de las xliffetiquetas alrededor de los especificadores de formato? ¿Qué valor adicional agregan en lugar de usar solo los especificadores %sy %d?
Richard Le Mesurier
El atributo "nombre" en la etiqueta xliff es solo una forma de dar una pista al traductor sobre lo que se sustituirá allí. A veces no es fácil adivinar lo que significa "% s".
hugomg
3

En Kotlin solo necesita establecer su valor de cadena de esta manera:

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

Cree una vista de texto en su diseño:

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

Luego haga esto en su código si está usando Anko:

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

Es posible que necesite obtener sus recursos del contexto de la aplicación.

msbodw001
fuente
55
¿Cómo es eso diferente a los ejemplos de Java? No veo ninguna diferencia
Janusz Hain
1

en res / values ​​/ string.xml

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

en código java

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

Si desea escribir porcentaje (%), duplíquelo:

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

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

Si se escribe simplemente %1$d%, obtendrá el error: Format string 'percent' is not a valid format string so it should not be passed to String.format.

CoolMind
fuente
0

¡Si! puede hacerlo sin escribir ningún código Java / Kotlin, solo XML utilizando esta pequeña biblioteca que creé, que lo hace en el momento de la compilación, para que su aplicación no se vea afectada por ella: https://github.com/LikeTheSalad/android -cadena-referencia

Uso

Sus cuerdas:

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

La cadena generada después de construir:

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

Una solución directa de Kotlin al problema:

strings.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
fuente
0

En su archivo de cadena use esto

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

Y en su código use como corresponda

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

Versión de Kotlin de la respuesta aceptada ...

val res = resources
val text = String.format(res.getString(R.string.welcome_messages), username, mailCount)
jesses.co.tt
fuente
3
La forma más correcta es usar el resources.getString(int, ... args)método con argumentos en lugar de String.format. Tampoco hay detalles específicos de kotlin en este código, aparte de la valpalabra clave. Ver respuesta de msbodw001
dant3