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.