Android TextView: "No concatene el texto que se muestra con setText"

136

Estoy configurando el texto usando setText () de la siguiente manera.

prodNameView.setText("" + name);

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

En eso, el primero es de uso simple y el segundo es configurar el texto con el formato del texto.

Android Studio es muy interesante, utilicé Menú Analyze -> Code Cleanupy recibí sugerencias sobre las dos líneas anteriores.

ingrese la descripción de la imagen aquí

No concatene el texto que se muestra con setText. Use una cadena de recursos con marcadores de posición. menos ... (Ctrl + F1)

Al llamar a TextView # setText:

  • Nunca llame a Number # toString () para formatear números; no manejará separadores de fracciones y dígitos específicos de la localidad correctamente. Considere usar el formato String # con las especificaciones de formato adecuadas (% do% f) en su lugar.
  • No pase un literal de cadena (por ejemplo, "Hola") para mostrar texto. El texto codificado no se puede traducir correctamente a otros idiomas. Considere usar cadenas de recursos de Android en su lugar.
  • No cree mensajes concatenando fragmentos de texto. Dichos mensajes no se pueden traducir correctamente.

¿Qué puedo hacer por esto? ¿Alguien puede ayudar a explicar qué es y qué debo hacer?

Pratik Butani
fuente
1
Eso significa que solo debes pasar un Stringinto setText(). Ej: setText(name)en lugar de setText("" + name). Porque si concatena texto, no se traducirá como si usara texto codificado como el mensaje notifica
Mr Neo
Pero dará NPEsi namees asíNULL
Pratik Butani
comprobar nameno es NULLantes de usar la setText()función.
Sr. Neo
2
No debe concatenar un recurso de cadena con algún valor, en su lugar use marcadores de posición en su recurso de cadena. Entonces, en su string.xml lo hace: <string name="string_product_rate_with_ruppe_sign">Something %1$d</string> Y en su código java hace algo como esto: prodOriginalPriceView.setText(getString(R.string.string_product_rate_with_ruppe_sign), price); (puede formatear en el archivo xml: [ developer.android.com/guide/topics/resources/…
CodeBreakers

Respuestas:

294

Resource tiene la versión de getString sobrecargada que toma un varargstipo Object: getString (int, java.lang.Object ...) . Si configura correctamente su cadena en strings.xml, con los marcadores de posición correctos, puede usar esta versión para recuperar la versión formateada de su cadena final. P.ej

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

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

android devolverá una cadena con

 "Hello Test! you have 0 new messages"

Acerca de setText("" + name);

Tu primer ejemplo prodNameView.setText("" + name);no tiene ningún sentido para mí. TextView puede manejar valores nulos. Si el nombre es nulo, no se dibujará ningún texto.

Cinta negra
fuente
1
suponiendo que en su BigDecimal que llamará valor flotante: Añadir %1$fa la cadena, en strings.xml y luego llamarsetText(getString(R.string.string_product_rate_with_ruppe_sign, new BigDecimal(price).setScale(2, RoundingMode.UP).floatValue() ));
Blackbelt
está en la segunda parte de la respuesta. Echa un vistazo
Blackbelt
Quiero mostrar un número entero .String significa $ sy Decimal $ d. Entonces, ¿significa entero?
reegan29
si te refieres al "marcador de posición" que puedes usar %1$d. @ reegan29
Blackbelt
3
Para cualquiera que busque la API que enumera los tipos de formatos: developer.android.com/reference/java/util/Formatter#syntax
Brent Sandstrom
34

No se confunda con % 1 $ s y % 2 $ d en el answer.Here aceptada es un poca información adicional.

  • Los especificadores de formato pueden tener la siguiente sintaxis:

% [ argument_index$]format_specifier

  1. El argumento_índice opcional se especifica como un número que termina con un "$" después del "%" y selecciona el argumento especificado en la lista de argumentos. El primer argumento está referenciado por "1 $" , el segundo por "2 $" , etc.
  2. El especificador de formato requerido es un carácter que indica cómo se debe formatear el argumento. El conjunto de conversiones válidas para un argumento dado depende del tipo de datos del argumento .

Ejemplo

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

Hola Test! tienes 0nuevos mensajes

Su string resource:

<string name = "welcome_messages"> ¡Hola %1$s! Tienes %2$dnuevos mensajes </ string>

Haga lo string substitutionque se indica a continuación:

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

Nota:

  • % 1 $ s se sustituirá por la cadena "Prueba"
  • % 2 $ d será sustituido por la cadena "0"
Rissmon Suresh
fuente
16

Me encontré con el mismo mensaje de error de pelusa y lo resolví de esta manera.

Inicialmente mi código era:

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

Tuve el siguiente error

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

Entonces, agregué esto a strings.xml

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

Cuál es mi "" inicial + un marcador de posición para mi número (cantidad).

Nota : Mi quantityvariable se definió previamente y es lo que quería agregar a la cadena. Mi código como resultado fue

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

Después de esto, mi error desapareció. El comportamiento en la aplicación no cambió y mi cantidad continuó mostrándose como quería ahora sin un error de pelusa.

usuario1580203
fuente
10

Debe verificar este hilo y usar un marcador de posición como el suyo (no probado)

<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);
ThomasThiebaud
fuente
10

No concatene texto dentro de su método setText () , concatene lo que quiera en una cadena y ponga ese valor de cadena dentro de su método setText () .

Ej: forma correcta

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

No concatene dentro de setText () como

text.setText(hrs+":"+String.format("%02d", mins)+":"+String.format("%02d", secs));
Ashana.Jackol
fuente
¿Por qué? ¿Qué ventajas tiene uno otro?
Fureeish
4

El problema es porque está agregando ""al principio de cada cadena.

lint analizará los argumentos que se pasan setTexty generará advertencias; en su caso, la siguiente advertencia es relevante:

No cree mensajes concatenando fragmentos de texto. Dichos mensajes no se pueden traducir correctamente.

ya que estás concatenando cada cadena con "".

elimine esta concatenación ya que los argumentos que está pasando ya son texto. Además, puede usarlo .toString()si es necesario en cualquier otro lugar en lugar de concatenar su cadena con""

Rahul Tiwari
fuente
0

Si no necesita admitir i18n, puede deshabilitar esta comprobación de pelusas en Android Studio

Archivo -> Configuración -> Editor -> Inspecciones -> Android -> Lint -> TextView Internationalization (desmarque esto)

ssynhtn
fuente
0

Puedes usar esto, me funciona

title.setText(MessageFormat.format("{0} {1}", itemList.get(position).getOppName(), itemList.get(position).getBatchNum()));
bahman karami
fuente
0
prodNameView.setText("" + name); //this produce lint error

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

No te enojes, es demasiado simple.

String firstname = firstname.getText().toString();
String result = "hi "+ firstname +" Welcome Here";
            mytextview.setText(result);
mwaqas
fuente