Android TextView: "Non concatenare il testo visualizzato con setText"


136

Sto impostando il testo usando setText () nel modo seguente.

prodNameView.setText("" + name);

prodOriginalPriceView.setText("" + String.format(getString(R.string.string_product_rate_with_ruppe_sign), "" + new BigDecimal(price).setScale(2, RoundingMode.UP)));

In quello il primo è un uso semplice e il secondo è l'impostazione del testo con formattazione del testo.

Android Studio è molto interessante, ho usato Menu Analyze -> Code Cleanupe ho ricevuto suggerimenti su due righe come.

inserisci qui la descrizione dell'immagine

Non concatenare il testo visualizzato con setText. Usa stringa di risorse con segnaposto. meno ... (Ctrl + F1)

Quando si chiama TextView # setText:

  • Non chiamare mai Number # toString () per formattare i numeri; non gestirà correttamente i separatori di frazione e le cifre specifiche della locale. Prendi invece in considerazione l'uso del formato String # con le specifiche di formato appropriate (% d o% f).
  • Non passare una stringa letterale (ad esempio "Ciao") per visualizzare il testo. Il testo codificato non può essere tradotto correttamente in altre lingue. Prendi invece in considerazione l'utilizzo di stringhe di risorse Android.
  • Non creare messaggi concatenando blocchi di testo. Tali messaggi non possono essere tradotti correttamente.

Cosa posso fare per questo? Chiunque può aiutare a spiegare qual è la cosa e cosa devo fare?


1
Ciò significa che si dovrebbe passare solo Stringin setText(). Es: setText(name)al posto di setText("" + name). Perché se concateni il testo, non verrà tradotto come se usassi il testo hardcoded come notifica del messaggio
Mr Neo,

Ma darà NPEse nameèNULL
Pratik Butani il

il controllo namenon avviene NULLprima di utilizzare la setText()funzione.
Mr Neo,

2
Non è necessario concaticare una risorsa String con un valore, ma utilizzare segnaposto nella risorsa stringa. Quindi nel tuo string.xml lo fai: <string name="string_product_rate_with_ruppe_sign">Something %1$d</string> E nel tuo codice java fai qualcosa del genere: prodOriginalPriceView.setText(getString(R.string.string_product_rate_with_ruppe_sign), price); (puoi fare la formattazione nel file xml: [ developer.android.com/guide/topics/resources/…
CodeBreakers

Risposte:


294

La risorsa ha la versione get gettrload di getString che accetta un varargstipo Object: getString (int, java.lang.Object ...) . Se si imposta correttamente la stringa in strings.xml, con i segnaposti corretti, è possibile utilizzare questa versione per recuperare la versione formattata della stringa finale. Per esempio

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

utilizzando getString(R.string.welcome_message, "Test", 0);

Android restituirà una stringa con

 "Hello Test! you have 0 new messages"

Di setText("" + name);

Il tuo primo esempio, prodNameView.setText("" + name);non ha alcun senso per me. TextView è in grado di gestire valori null. Se il nome è nullo, non verrà disegnato alcun testo.


1
supponendo che sul tuo BigDecimal chiamerai il valore float: Aggiungi %1$falla tua stringa, in strings.xml e poi chiameraisetText(getString(R.string.string_product_rate_with_ruppe_sign, new BigDecimal(price).setScale(2, RoundingMode.UP).floatValue() ));
Blackbelt

è nella seconda parte della risposta.
Dai

Voglio mostrare un numero intero. La stringa è $ s e Decimale $ d. Quindi integer sta per?
reegan29,

se intendi il "segnaposto" che puoi usare %1$d. @ reegan29
Blackbelt,

3
Per chiunque cerchi l'API che elenca i tipi di formati: developer.android.com/reference/java/util/Formatter#syntax
Brent Sandstrom,

34

Non fatevi confondere con % 1 $ s e % 2 $ d nel accettato l'answer.Here è a pochi informazioni extra.

  • Gli identificatori di formato possono essere della seguente sintassi:

% [ argument_index$]format_specifier

  1. L' argomento_indice facoltativo viene specificato come un numero che termina con un "$" dopo "%" e seleziona l'argomento specificato nell'elenco degli argomenti. Il primo argomento fa riferimento a "1 $" , il secondo a "2 $" , ecc.
  2. L'identificatore di formato richiesto è un carattere che indica come deve essere formattato l'argomento. L'insieme di conversioni valide per un determinato argomento dipende dal tipo di dati dell'argomento .

Esempio

Creeremo la seguente stringa formattata in cui le parti grigie vengono inserite a livello di codice.

Ciao Test! hai 0nuovi messaggi

Il tuo string resource:

<String name = "welcome_messages"> Ciao, %1$s! Hai %2$dnuovi messaggi </ stringa>

Fare string substitutioncome indicato di seguito:

getString (R.string.welcome_message, "Test", 0);

Nota:

  • % 1 $ s sarà sostituito dalla stringa "Test"
  • % 2 $ d sarà sostituito dalla stringa "0"

16

Ho incontrato lo stesso messaggio di errore lanugine e risolto in questo modo.

Inizialmente il mio codice era:

private void displayQuantity(int quantity) {
    TextView quantityTextView = (TextView) findViewById(R.id.quantity_text_view);
    quantityTextView.setText("" + quantity);
}

Ho ricevuto il seguente errore

Do not concatenate text displayed with setText. Use resource string with placeholders.

Quindi, l'ho aggiunto a strings.xml

<string name="blank">%d</string>

Qual è il mio "" iniziale + un segnaposto per il mio numero (quantità).

Nota : la mia quantityvariabile era stata precedentemente definita ed è ciò che volevo aggiungere alla stringa. Il mio codice era di conseguenza

private void displayQuantity(int quantity) {
    TextView quantityTextView = (TextView) findViewById(R.id.quantity_text_view);
    quantityTextView.setText(getString(R.string.blank, quantity));
}

Dopo questo, il mio errore è andato via. Il comportamento nell'app non è cambiato e la mia quantità ha continuato a essere visualizzata come volevo ora senza errori di lanugine.


10

Dovresti controllare questa discussione e usare un segnaposto come il suo (non testato)

<string name="string_product_rate_with_ruppe_sign">Price : %1$d</string>

String text = String.format(getString(R.string.string_product_rate_with_ruppe_sign),new BigDecimal(price).setScale(2, RoundingMode.UP));
prodOriginalPriceView.setText(text);

10

Non concatenare il testo all'interno del metodo setText () , Concatena ciò che vuoi in una stringa e inserisci quel valore String nel metodo setText () .

es: modo corretto

int min = 120;
int sec = 200;
int hrs = 2;

String minutes = String.format("%02d", mins);
            String seconds = String.format("%02d", secs);
            String newTime = hrs+":"+minutes+":"+seconds;

text.setText(minutes);

Non concatenare all'interno di setText () come

text.setText(hrs+":"+String.format("%02d", mins)+":"+String.format("%02d", secs));

Perché? Quali sono i vantaggi dell'altro?
Fureeish,

4

il problema è perché stai aggiungendo ""all'inizio di ogni stringa.

lint eseguirà la scansione degli argomenti passati setTexte genererà avvisi, nel tuo caso è rilevante il seguente avviso:

Non creare messaggi concatenando blocchi di testo. Tali messaggi non possono essere tradotti correttamente.

mentre concatenate ogni stringa con "".

rimuovi questa concatenazione poiché gli argomenti che stai passando sono già di testo. Inoltre, puoi usare .toString()se richiesto in qualsiasi altro posto invece di concatenare la stringa con""


0

Se non è necessario supportare i18n, è possibile disabilitare questo controllo lanugine in Android Studio

File -> Impostazioni -> Editor -> Ispezioni -> Android -> Lint -> Internazionalizzazione TextView (deseleziona)


0

Puoi usarlo, funziona per me

title.setText(MessageFormat.format("{0} {1}", itemList.get(position).getOppName(), itemList.get(position).getBatchNum()));

0
prodNameView.setText("" + name); //this produce lint error

val nameStr="" + name;//workaround for quick warning fix require rebuild
prodNameView.setText(nameStr);

-1

Non arrabbiarti, è troppo semplice.

String firstname = firstname.getText().toString();
String result = "hi "+ firstname +" Welcome Here";
            mytextview.setText(result);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.