Símbolo de porcentagem XML do Android


309

Eu tenho uma matriz de seqüências de caracteres em que o %símbolo é usado. Formato adequado para usar o %is %. Quando eu tenho uma string nessa matriz com várias, %isso me dá esse erro.

 Multiple annotations found at this
 line:
 - error: Multiple substitutions specified in non-positional format;
   did you mean to add the formatted="false" attribute?
 - error: Found tag </item> where </string-array> is expected

6
Você pode postar o XML que está causando esse erro? Pode ser muito difícil identificar um problema sem ver sua causa.
Chris Cashwell

esse é um erro que pode ser facilmente replicado por qualquer sequência com 2 ou mais% de símbolos.
Zaid

Se não estiver procurando um objetivo de formatação, é a melhor maneira de realizar.
Shishir Gupta

No meu caso, inseri incorretamente o parâmetro de formatação como 1% $ s, em vez de% 1 $ s.
Ashokchakravarthi Nagarajan 30/03

Respostas:


467

A Ferramenta de empacotamento de ativos Android ( aapt) tornou-se muito rigorosa em sua versão mais recente e agora é usada para todas as versões do Android. O erro aapt que você está recebendo é gerado porque não permite mais especificadores de formato não posicionais .

Aqui estão algumas idéias de como você pode incluir o símbolo% em suas sequências de recursos.

Se você não precisar de nenhum especificador ou substituição de formato em sua string, basta usar o formattedatributo e configurá-lo para false:

<string formatted="false">%a + %a == 2%a</string>

Nesse caso, a string não é usada como uma string de formato para Formatterque você não precise escapar dos% -symbols. A sequência resultante é "% a +% a == 2% a".

Se você omitir o formatted="false"atributo, a sequência será usada como uma sequência de formatação e você precisará escapar dos% -symbols. Isso é feito corretamente com o dobro de%:

<string>%%a + %%a == 2%%a</string>

Agora aaptnão há erros, mas dependendo de como você a usa, a sequência resultante pode ser "%% a + %% a == 2 %% a" se a Formatterfor chamada sem nenhum argumento de formato :

Resources res = context.getResources();

String s1 = res.getString(R.string.str);
// s1 == "%%a + %%a == 2%%a"

String s2 = res.getString(R.string.str, null);
// s2 == "%a + %a == 2%a"

Sem nenhum código e xml, é difícil dizer qual é exatamente o seu problema, mas espero que isso ajude você a entender um pouco melhor os mecanismos.


1
Eu selecionei isso como a resposta porque deveria funcionar, mas aparentemente existe um bug que estou encontrando com essa string, então decidi usar %% e "XXX.replaceAll (" %% ","% ");"
Zaid

4
usando formatado = false funciona bem. Foi assim que eu o usei: <string name = "information_description" formatted = "false"> \ 'Sweet \' 10% a 20% até 35% de açúcar em peso </string>
Alguém em algum lugar

1
formatado = false também funciona bem para mim. Usando %%, ele literalmente apareceu como %% no meu dispositivo e emulador. #
Samwize

formatado = false funcionou bem para mim no passado. agora (ADT 22), por algum motivo, não. e se eu usar: "str = mContext.getString (R.string.str," hello ")", ele receberá este aviso de fiapos: "Format string 'str' não é uma string de formato válida, portanto não deve ser passada para String.format "
desenvolvedor android

1
Se você estiver acessando a partir de <string-array />, para porcentagem de impressão, use \ u0025. Isso funcionou para mim.
precisa

157

Para permitir que o aplicativo use seqüências de caracteres formatadas de recursos, você deve corrigir seu xml. Então, por exemplo

<string name="app_name">Your App name, ver.%d</string>

deve ser substituído por

<string name="app_name">Your App name, ver.%1$d</string>

Você pode ver isso para detalhes.


2
Obrigado, você forneceu o link que faltava - literalmente.
akauppi

22
Para substituição múltipla parâmetro (por exemplo com cordas), utilização %1$s, %2$setc.
CJBS

1
quem lerá uma resposta tão grande para essa coisinha? Obrigado, eu desço para encontrar você.
Janaka R Rajapaksha

73

Você pode escapar% usando %% para analisador XML, mas é mostrado duas vezes no dispositivo.

Para mostrá-lo uma vez, tente o seguinte formato: \%%

Por exemplo

<string name="zone_50">Fat Burning (50\%% to 60\%%)</string> 

é mostrado como Fat Burning (50% to 60%)no dispositivo


6
\ %% causa falhas no Nexus 4 4.2.1. Não testei outros.
21413 Jon Willis

Isso funciona bem e é fácil quando você já sabe a porcentagem que deseja incluir em suas strings, em vez de usar o formatador de strings e sempre ter que definir esses valores codificados programaticamente.
portfoliobuilder

Isso também caiu para mim no Nexus 5.1.1. A resposta do @ViliusK é a correta.
Chan Jing Hong

2
basta usar %% em vez de% #
Sundeep1501 #

37

Usar

<string name="win_percentage">%d%% wins</string>

para obter

80% wins como uma sequência formatada.

Estou usando o String.format()método para obter o número inserido em vez de %d.


12

No seu arquivo strings.xml, você pode usar qualquer sinal Unicode desejado.

Por exemplo, o número Unicode para o sinal de porcentagem é 0025:

<string name="percent_sign">&#x0025;</string>

Você pode ver uma lista abrangente de sinais Unicode aqui


1
Isso não faz sentido. & # x0025; e% são idênticos em um arquivo xml.
BeniBela

O arquivo de recurso é convertido em um recurso Java e, ao fazer isso, o %caractere retorna. Receio que isso não resolva o problema.
Paul Lammertsma 28/03

9

para escapar do símbolo de porcentagem, você só precisa de %%

por exemplo :

String.format("%1$d%%", 10)

retorna "10%"


1
Sua resposta é praticamente o mesmo como várias outras respostas existentes
Ben Rhys-Lewis

... e errado, porque 10%não retorna %10. FIY: Ao usar, String.formatvocê deve especificar sempre o Local. Pode ser realmente surpreso quando você não colocar Locale e utilizar locale árabe para formatar números ...
mtrakal

7

Não é exatamente o seu problema, mas um problema semelhante.

Se você tiver mais de uma formatação em sua entrada de string, não deverá usar "% s" várias vezes.

NÃO:

<string name="entry">Planned time %s - %s (%s)</string>

FAZ :

<string name="entry">Planned time %1$s - %2$s (%3$s)</string>

5

Você pode escapar do% em xml com %%, mas precisa definir o texto no código, não no layout xml.


1
Sim, ele escapa com o dobro de% e compila muito bem. Mas quando executado em emulador, ou mesmo em dispositivos, ele pode aparecer como %%.
samwize 19/07/11

5

Pode ser que o IDE se torne muito rígido.

A ideia é boa: em geral, você deve especificar a ordem das variáveis ​​de substituição para adicionar recursos para outro idioma, seu código java não precisará ser alterado. No entanto, existem dois problemas com isso:

Em primeiro lugar, uma sequência como:

You will need %.5G %s

para ser usado como Você precisará de 2.1200 mg e terá a mesma ordem em qualquer idioma, pois essa quantidade de massa é sempre representada cientificamente nessa ordem.

A segunda é que, se você colocar a ordem das variáveis ​​em qualquer idioma em que seus recursos padrão forem especificados (por exemplo, inglês), precisará especificar apenas as posições nas cadeias de recursos para idiomas e usar uma ordem diferente para o idioma padrão.

A boa notícia é que isso é simples de corrigir. Mesmo que não seja necessário especificar as posições e o IDE estar sendo excessivamente rigoroso, apenas especifique-as de qualquer maneira. Para o exemplo acima, use:

Você precisará de% 1 $ .5G% 2 $ s


4

Um método complicado: usar um pequeno sinal de porcentagem como abaixo

 <string name="zone_50">Fat Burning (50&#65130; to 60&#65130;)</string> 

Porcentagem na Wikipedia


3

Tente este (à direita):

<string name="content" formatted="false">Great application %s  ☞  %s  ☞  %s \\n\\nGo to download this application %s</string>


-1

Suponha que você queira mostrar (50% OFF) e insira 50 no tempo de execução. Aqui está o código:

<string name="format_discount"> (
<xliff:g id="discount">%1$s</xliff:g>
<xliff:g id="percentage_sign">%2$s</xliff:g>
 OFF)</string>

Na classe java, use este código:

String formattedString=String.format(context.getString(R.string.format_discount),discountString,"%");
holder1.mTextViewDiscount.setText(formattedString);

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.