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


495

É possível ter espaços reservados em valores de seqüência string.xmlque possam ser atribuídos a valores em tempo de execução?

Exemplo:

alguma string PLACEHOLDER1 um pouco mais de string



@HarishGyanani Não, este é mais antigo, deve-se unir a este em vez de #
— Danh

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.


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

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.


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


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.


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


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.


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>

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 )

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

-1

Versão Kotlin da resposta aceita ...

val res = resources
val text = String.format(res.getString(R.string.welcome_messages), username, mailCount)

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.