É possível adicionar dinamicamente String a String.xml no Android?

Respostas:

1035

Formatação e estilo

Sim, consulte o seguinte em Recursos da cadeia de caracteres: Formatação e estilo

Se você precisar formatar suas strings usando String.format(String, Object...), poderá fazê-lo colocando seus argumentos de formato no recurso de strings. Por exemplo, com o seguinte recurso:

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

Neste exemplo, a string de formato possui dois argumentos: %1$sé uma string e %2$dé um número decimal. Você pode formatar a string com argumentos do seu aplicativo, como este:

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

Uso básico

Observe que getStringhá uma sobrecarga que usa a string como uma string de formato:

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

Plurais

Se você precisar lidar com plurais, use o seguinte:

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

O primeiro mailCountparâmetro é usado para decidir qual formato usar (único ou plural); os outros parâmetros são suas substituições:

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

Consulte Recursos de seqüência de caracteres: Plurais para obter mais detalhes.

Megha Joshi - GoogleTV DevRel
fonte
61
A chamada String.format no primeiro exemplo de código não é realmente necessária, Resources.getString () suporta formatação, consulte: developer.android.com/reference/android/content/res/… , java.lang.Object ...)
Arnaud
16
para plurais em String.xml você precisa dar id como R.plurals.welcome_messages vez de R.string.welcome_messages
om252345
coisa plural retornando apenas a última string do item ... alguma idéia de como obter uma string anexada.
CoDe
1
Ao usar esse método para formatar sua seqüência, removeu quaisquer meta tags você pode ter usado tais como hyperlinks etc que poderiam ter sido contidos no texto seqüência de caracteres XML
Jonathan
4
String significa% 1 $ s, decimal para% 2 $ d e inteiro significa o que? qual é o significado% 1,% 2.Esta contagem do parâmetro? .se eu quero o terceiro parâmetro É mencionada% 3?
reegan29
260

Resposta complementar

Quando vi pela primeira vez %1$se %2$dna resposta aceita, não fazia sentido. Aqui está um pouco mais de explicação.

Eles são chamados de especificadores de formato. Na sequência xml, eles estão na forma de

%[parameter_index$][format_type] 
  • % : O sinal de porcentagem marca o início do especificador de formato.
  • índice do parâmetro : este é um número seguido por um cifrão. Se você tivesse três parâmetros que você queria inserir na corda, em seguida, eles seriam chamados 1$, 2$e 3$. A ordem em que você as coloca na cadeia de recursos não importa, apenas a ordem em que você fornece os parâmetros.
  • tipo de formato : existem várias maneiras de formatar as coisas ( consulte a documentação ). Aqui estão alguns comuns:

    • s corda
    • d número inteiro decimal
    • f número de ponto flutuante

Exemplo

Criaremos a seguinte string formatada em que as partes cinzas são inseridas programaticamente.

Minha irmã Marytem 12anos.

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

  • Eu poderia usar getStringporque estava em uma atividade. Você pode usar context.getResources().getString(...)se não estiver disponível.
  • String.format() também formatará uma String.
  • Os termos 1$e 2$não precisam ser usados ​​nessa ordem. Ou seja, 2$pode vir antes 1$. Isso é útil ao internacionalizar um aplicativo para idiomas que usam uma ordem de palavras diferente.
  • Você pode usar um especificador de formato %1$svárias vezes no xml, se desejar repeti-lo.
  • Use %%para obter o %personagem real .
  • Para obter mais detalhes, leia o seguinte tutorial útil: Dica rápida do SDK do Android: Formatando cadeias de recursos
Suragch
fonte
125

Quando você deseja usar um parâmetro do arquivo strings.xml real sem usar nenhum 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>

Isso não funciona nos arquivos de recursos, ou seja, as variáveis ​​devem ser copiadas em cada arquivo XML que precisa delas.

Oded Breiner
fonte
Essa é uma boa resposta, exceto quando você tem um parâmetro dentro de <! [CDATA [& param; ]]>
Hermann Poilpre 18/12/16
2
Existe alguma maneira de definir a <!DOCTYPE... ]>peça em um arquivo separado e incluí-la em vários arquivos de recursos? Algum truque para conseguir isso?
prom85
18

Estava procurando o mesmo e finalmente encontrou a seguinte solução muito simples. Melhor: funciona imediatamente.
1. altere seu recurso de string:

<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. use substituição de string:

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

onde c é o contexto, name é uma variável de string e conta sua variável int

Você precisará incluir

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

em seu res / strings.xml. Funciona para mim. :)

user3016503
fonte
2
Qual é o sentido das xlifftags nos especificadores de formato? Que valor extra eles agregam em vez de usar os especificadores %se %dpor conta própria?
Richard Le Mesurier
O atributo "name" na tag xliff é apenas uma maneira de dar uma dica ao tradutor sobre o que será substituído lá. Às vezes, não é fácil adivinhar o que significa "% s".
hugomg 6/11/19
3

No Kotlin, você só precisa definir o valor da string assim:

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

Crie uma exibição de texto no seu layout:

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

Em seguida, faça isso no seu código se você estiver usando o 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))  

Pode ser necessário obter seus recursos no contexto do aplicativo.

msbodw001
fonte
5
Como isso é diferente dos exemplos java? Eu não vejo nenhuma diferença
Janusz Hain
1

em res / values ​​/ string.xml

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

no 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
fonte
1

Se você deseja escrever por cento (%), duplique-o:

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

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

Se você escrever simplesmente %1$d%, você receberá o erro: Format string 'percent' is not a valid format string so it should not be passed to String.format.

CoolMind
fonte
0

Sim! você pode fazer isso sem escrever nenhum código Java / Kotlin, apenas XML, usando esta pequena biblioteca que eu criei, que faz isso no momento da construção, para que seu aplicativo não seja afetado por ele: https://github.com/LikeTheSalad/android -string-reference

Uso

Suas cordas:

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

A sequência gerada após a construção:

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

Uma solução direta da Kotlin para o 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
fonte
0

No seu arquivo de string, use este

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

E no seu código, use da mesma maneira

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

Versão Kotlin da resposta aceita ...

val res = resources
val text = String.format(res.getString(R.string.welcome_messages), username, mailCount)
jesses.co.tt
fonte
3
A maneira mais correta é usar o resources.getString(int, ... args)método com argumentos em vez de String.format. Também não há detalhes específicos do kotlin neste código, além da valpalavra - chave. Veja a resposta de msbodw001
dant3