Android TextView: "Не об'єднуйте текст, який відображається за допомогою setText"


136

Я встановлюю текст за допомогою setText () наступним чином.

prodNameView.setText("" + name);

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

У цьому Перший є простим у використанні, а Другим - це встановлення тексту з форматуванням тексту.

Android Studio настільки цікавий, що я скористався Меню, Analyze -> Code Cleanupі я отримав пропозицію щодо двох вище рядків.

введіть тут опис зображення

Не з'єднуйте текст, який відображається за допомогою setText. Використовуйте рядок ресурсів із заповнювачами. менше ... (Ctrl + F1)

Під час виклику TextView # setText:

  • Ніколи не дзвоніть номер # toString () для форматування чисел; він не буде належним чином обробляти роздільники дробів та конкретні для локальної цифри. Спробуйте використовувати формат String # із належними специфікаціями формату (% d або% f).
  • Не передайте рядковий літерал (наприклад, "Hello") для відображення тексту. Текст із твердим кодом неможливо правильно перекласти на інші мови. Спробуйте використовувати замість них рядки ресурсів Android.
  • Не створюйте повідомлення за допомогою об'єднання текстових фрагментів. Такі повідомлення неможливо правильно перекласти.

Що я можу зробити для цього? Кожен може допомогти пояснити, що це за річ і що мені робити?


1
Це означає, що ви повинні перейти лише Stringв setText(). Наприклад: setText(name)замість setText("" + name). Тому що, якщо ви з’єднаєте текст, він не буде перекладений так, як ви використовуєте текст із твердим кодом як повідомлення про це
Містер Нео

Але це дасть, NPEякщо nameєNULL
Пратік Бутані

перевірка nameне NULLперед використанням setText()функції.
Містер Нео

2
Не слід прив'язувати ресурс String до якогось значення, натомість використовувати заповнювачі у вашому рядковому ресурсі. Отже, у своєму string.xml ви робите: <string name="string_product_rate_with_ruppe_sign">Something %1$d</string> І у своєму коді Java ви робите щось подібне: prodOriginalPriceView.setText(getString(R.string.string_product_rate_with_ruppe_sign), price); (ви можете виконати форматування у файлі xml: [ developer.android.com/guide/topics/resources/…
CodeBreakers

Відповіді:


294

У ресурсі є перевантажена версія getString, яка приймає varargsтип Object: getString (int, java.lang.Object ...) . Якщо ви правильно налаштували рядок у strings.xml з правильними власниками місць, ви можете використовувати цю версію для отримання відформатованої версії остаточного рядка. Напр

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

використовуючи getString(R.string.welcome_message, "Test", 0);

android поверне String з

 "Hello Test! you have 0 new messages"

Про setText("" + name);

Ваш перший Приклад prodNameView.setText("" + name);не має для мене ніякого сенсу. TextView вміє обробляти нульові значення. Якщо ім’я недійсне, текст не буде намальований.


1
якщо припустити, що на BigDecimal ви будете називати значення float: Додати %1$fдо рядка, у strings.xml, а потім зателефонуватиsetText(getString(R.string.string_product_rate_with_ruppe_sign, new BigDecimal(price).setScale(2, RoundingMode.UP).floatValue() ));
Blackbelt

це у другій частині відповіді. Подивіться
Блекбельт

Я хочу показати Integer .String стоїть $ s і Decimal $ d. Так означає ціле число?
reegan29

якщо ви маєте на увазі "заповнювач місця", який ви можете використовувати %1$d. @ Reegan29
Blackbelt

3
Для всіх, хто шукає API, перелічуючи типи форматів: developer.android.com/reference/java/util/Formatter#syntax
Brent Sandstrom

34

Не плутайте з % 1 $ s та % 2 $ d у прийнятій відповіді. Ось кілька додаткових відомостей.

  • Специфікатори формату можуть мати такий синтаксис:

% [ argument_index$]format_specifier

  1. Необов’язковий argument_index вказується як число, що закінчується на "$" після "%" і вибирає вказаний аргумент у списку аргументів. Перший аргумент посилається на "1 $" , на другий - "2 $" тощо.
  2. Необхідний специфікатор формату - символ, що вказує на те, як слід форматувати аргумент. Набір допустимих перетворень для даного аргументу залежить від типу даних аргументу .

Приклад

Ми створимо наступну відформатовану рядок, куди програмно вставляються сірі частини.

Привіт Test! у вас є 0нові повідомлення

Ваше string resource:

<Рядок ім'я = "welcome_messages"> Привіт, %1$s! У вас є %2$dнові повідомлення </string>

Виконайте наступне string substitution:

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

Примітка:

  • % 1 $ s буде замінено рядком "Тест"
  • % 2 $ d буде замінено рядком "0"

16

Я наткнувся на те саме повідомлення про помилку ворсу і вирішив це таким чином.

Спочатку мій код був:

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

Я отримав таку помилку

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

Отже, я до цього додав strings.xml

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

Що є моїм початковим "" + заповнювачем для мого номера (кількості).

Примітка . Моя quantityзмінна була раніше визначена і саме це я хотів додати до рядка. Мій код в результаті був

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

Після цього моя помилка пішла. Поведінка в додатку не змінилася, і моя кількість продовжувала відображатися так, як я цього хотіла зараз, без похибки.


10

Ви повинні перевірити цей потік і використовувати заповнювач, як його (не перевірено)

<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

Не з'єднуйте текст у вашому методі setText () , об'єднайте все, що завгодно у String, і введіть це значення String всередину методу setText () .

наприклад: правильний шлях

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

Не з'єднуйте всередині типу setText ()

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

Чому? Якими перевагами володіє одна в іншої?
Fureeish

4

проблема полягає в тому, що ви додаєте ""на початку кожного рядка.

lint сканує аргументи, які передаються setTextта генерує попередження, у вашому випадку таке попередження має значення:

Не створюйте повідомлення за допомогою об'єднання текстових фрагментів. Такі повідомлення неможливо правильно перекласти.

як ви об'єднуєте кожен рядок "".

видаліть цю конкатенацію, оскільки аргументи, які ви передаєте, вже є текстовими. Крім того, ви можете використовувати, .toString()якщо взагалі потрібно деінде, замість того, щоб поєднувати рядок із""


0

Якщо вам не потрібно підтримувати i18n, ви можете відключити цю перевірку в Android Studio

Файл -> Налаштування -> Редактор -> Інспекції -> Android -> Лінт -> Інтернаціоналізація TextView (зніміть прапорець)


0

Ви можете використовувати це, це працює для мене

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

Не з глузду, це занадто просто.

String firstname = firstname.getText().toString();
String result = "hi "+ firstname +" Welcome Here";
            mytextview.setText(result);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.