Android TextView: „Nie łącz tekstu wyświetlanego z setText”

148

Ustawiam tekst za pomocą setText () w następujący sposób.

prodNameView.setText("" + name);

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

W tym pierwszym jest proste użycie, a drugim jest ustawienie tekstu z formatowaniem tekstu.

Android Studio jest tak bardzo interesujące, że skorzystałem z Menu Analyze -> Code Cleanupi otrzymałem sugestię w dwóch powyższych liniach, takich jak.

wprowadź opis obrazu tutaj

Nie łącz tekstu wyświetlanego z setText. Użyj ciągu zasobów z symbolami zastępczymi. mniej ... (Ctrl + F1)

Podczas wywoływania TextView # setText:

  • Nigdy nie wywołuj Number # toString () w celu sformatowania liczb; nie będzie poprawnie obsługiwał separatorów ułamków i cyfr specyficznych dla ustawień regionalnych. Zamiast tego rozważ użycie formatu String # z odpowiednimi specyfikacjami formatu (% d lub% f).
  • Nie przekazuj literału ciągu (np. „Hello”), aby wyświetlić tekst. Tekst zakodowany na stałe nie może być poprawnie przetłumaczony na inne języki. Zamiast tego rozważ użycie ciągów zasobów systemu Android.
  • Nie twórz wiadomości przez łączenie fragmentów tekstu. Takie wiadomości nie mogą być poprawnie przetłumaczone.

Co mogę z tym zrobić? Każdy może pomóc wyjaśnić, co to jest i co mam zrobić?

Pratik Butani
źródło
1
Oznacza to, że należy przekazać tylko Stringdo setText(). Np .: setText(name)zamiast setText("" + name). Ponieważ jeśli połączysz tekst, nie zostanie on przetłumaczony tak, jak używasz tekstu zakodowanego na sztywno, o czym informuje wiadomość
Mr Neo
Ale da, NPEjeśli nametakNULL
Pratik Butani
sprawdzenie namenie jest NULLprzed użyciem setText()funkcji.
Pan Neo
3
Nie należy łączyć zasobu String z jakąś wartością, zamiast tego należy używać symboli zastępczych w zasobie ciągu. Więc w swoim string.xml robisz: <string name="string_product_rate_with_ruppe_sign">Something %1$d</string> A w swoim kodzie java robisz coś takiego: prodOriginalPriceView.setText(getString(R.string.string_product_rate_with_ruppe_sign), price); (możesz formatować w pliku xml: [ developer.android.com/guide/topics/resources/ ...
CodeBreakers

Odpowiedzi:

308

Zasób ma przeciążoną wersję getString, która przyjmuje plik varargs typ Object: getString (int, java.lang.Object ...) . Jeśli poprawnie skonfigurujesz swój ciąg w strings.xml, z odpowiednimi symbolami zastępczymi, możesz użyć tej wersji do pobrania sformatowanej wersji ostatecznego ciągu. Na przykład

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

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

android zwróci String z

 "Hello Test! you have 0 new messages"

O setText("" + name);

Twój pierwszy przykład prodNameView.setText("" + name);nie ma dla mnie żadnego sensu. TextView jest w stanie obsłużyć wartości null. Jeśli nazwa ma wartość null, tekst nie zostanie narysowany.

Czarny pas
źródło
1
zakładając, że na Twoim BigDecimal wywołasz wartość float: Dodaj %1$fdo swojego ciągu, w strings.xml, a następnie zadzwońsetText(getString(R.string.string_product_rate_with_ruppe_sign, new BigDecimal(price).setScale(2, RoundingMode.UP).floatValue() ));
Blackbelt
jest w drugiej części odpowiedzi. Spójrz
Blackbelt
1
Chcę pokazać liczbę całkowitą. Ciąg oznacza $ s, a wartość dziesiętną $ d. Więc liczba całkowita oznacza?
reegan29
jeśli masz na myśli „symbol zastępczy”, którego możesz użyć %1$d. @ reegan29
Blackbelt
3
Dla każdego, kto szuka API z listą typów formatów: developer.android.com/reference/java/util/Formatter#syntax
Brent Sandstrom
36

Nie daj się pomylić z % 1 $ s i % 2 $ d w zaakceptowanej odpowiedzi. Oto kilka dodatkowych informacji.

  • Specyfikatory formatu mogą mieć następującą składnię:

% [ argument_index$]format_specifier

  1. Opcjonalny argument_index jest określany jako liczba kończąca się na „$” po „%” i wybiera określony argument z listy argumentów. Do pierwszego argumentu odwołuje się „1 $” , do drugiego odwołuje się „2 $” itd.
  2. Wymagany specyfikator formatu to znak wskazujący, jak należy sformatować argument. Zestaw prawidłowych konwersji dla danego argumentu zależy od typu danych argumentu .

Przykład

Utworzymy następujący sformatowany ciąg, w którym szare części zostaną wstawione programowo.

Witam Test! masz 0nowe wiadomości

Twój string resource:

<string name = "welcome_messages"> Witaj %1$s! Masz %2$dnowe wiadomości </ string>

Wykonaj string substitutionponiższe czynności:

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

Uwaga:

  • % 1 $ s zostanie zastąpione ciągiem „Test”
  • % 2 $ d zostanie zastąpione ciągiem „0”
Rissmon Suresh
źródło
17

Natrafiłem na ten sam komunikat o błędzie kłaczków i rozwiązałem go w ten sposób.

Początkowo mój kod brzmiał:

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

Otrzymałem następujący błąd

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

Więc dodałem to do strings.xml

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

Który jest moim początkiem „” + miejsce na mój numer (ilość).

Uwaga : Moja quantityzmienna została wcześniej zdefiniowana i chciałem ją dołączyć do ciągu. W rezultacie mój kod był

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

Po tym mój błąd zniknął. Zachowanie w aplikacji nie zmieniło się, a moja ilość nadal wyświetlała się tak, jak chciałem, bez błędu kłaczków.

user1580203
źródło
11

Nie łącz tekstu wewnątrz metody setText () , łącz wszystko, co chcesz w ciągu znaków i umieść tę wartość ciągu w metodzie setText () .

np. właściwy sposób

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

Nie konkatenuj wewnątrz setText () jak

text.setText(hrs+":"+String.format("%02d", mins)+":"+String.format("%02d", secs));
Ashana.Jackol
źródło
Czemu? Jakie zalety ma jedno drugie?
Fureeish
10

Powinieneś sprawdzić ten wątek i użyć symbolu zastępczego, takiego jak jego (nie testowane)

<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
źródło
4

problem polega na tym, że dołączasz "" na początku każdego napisu.

lint skanuje argumenty przekazywane do setTexti generuje ostrzeżenia, w Twoim przypadku istotne jest następujące ostrzeżenie:

Nie twórz wiadomości przez łączenie fragmentów tekstu. Takie wiadomości nie mogą być poprawnie przetłumaczone.

ponieważ łączysz każdy ciąg z "" .

usuń to połączenie, ponieważ argumenty, które przekazujesz, są już tekstem. Możesz również użyć, .toString()jeśli w ogóle jest to wymagane, gdziekolwiek indziej, zamiast łączyć swój ciąg z""

Rahul Tiwari
źródło
1

Nie szalej, to zbyt proste.

String firstname = firstname.getText().toString();
String result = "hi "+ firstname +" Welcome Here";
            mytextview.setText(result);
mwaqas
źródło
0

Jeśli nie potrzebujesz obsługi i18n, możesz wyłączyć sprawdzanie kłaczków w Android Studio

Plik -> Ustawienia -> Edytor -> Inspekcje -> Android -> Lint -> Internacjonalizacja TextView (odznacz to)

ssynhtn
źródło
0

Możesz tego użyć, to działa dla mnie

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

val nameStr="" + name;//workaround for quick warning fix require rebuild
prodNameView.setText(nameStr);
SkorpEN
źródło