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

その1つ目は簡単な使用法で、2つ目は書式設定テキストを使用してテキストを設定する方法です。

Android Studioは非常に興味深いので、Menuを使用Analyze -> Code Cleanupして、上記の2行のような提案を受けました。

ここに画像の説明を入力してください

表示されたテキストをsetTextで連結しないでください。プレースホルダーでリソース文字列を使用します。少ない...(Ctrl + F1)

TextView#setTextを呼び出すとき

  • Number#toString()を呼び出して数値をフォーマットしないでください。小数区切りとロケール固有の数字は適切に処理されません。代わりに、適切なフォーマット指定(%dまたは%f)でString#formatを使用することを検討してください。
  • テキストを表示するために文字列リテラル(「Hello」など)を渡さないでください。ハードコードされたテキストは、他の言語に正しく翻訳できません。代わりにAndroidリソース文字列の使用を検討してください。
  • テキストチャンクを連結してメッセージを作成しないでください。このようなメッセージは適切に翻訳できません。

これのために私は何ができますか?誰もがそれが何で何をすべきかを説明するのを手伝ってくれる?


1
つまり、Stringinto だけを渡す必要がありますsetText()。例:のsetText(name)代わりにsetText("" + name)。テキストを連結する場合、メッセージ通知としてハードコードされたテキストを使用するように翻訳されないため
Mr Neo

しかし、それは与えるNPE場合nameであるNULL
Pratik Butani

チェックnameは機能NULLを使用setText()する前ではありません。
Neo氏

2
文字列リソースに何らかの値を連結するのではなく、文字列リソースでプレースホルダーを使用してください。だからあなたの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);

アンドロイドは文字列を返します

 "Hello Test! you have 0 new messages"

setText("" + name);

最初の例は、prodNameView.setText("" + name);私には意味がありません。TextViewはnull値を処理できます。名前がnullの場合、テキストは描画されません。


1
BigDecimalでfloat値を呼び出すと仮定します。strings.xmlで%1$f文字列に追加してから呼び出します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 $"で参照されます。
  2. 必須のフォーマット指定子は、引数のフォーマット方法を示す文字です。特定の引数の有効な変換のセットは、引数のデータ型によって異なります。

次のフォーマットされた文字列を作成し、灰色の部分をプログラムで挿入します。

こんにちはTest!あなたは持っている0新しいメッセージを

あなたstring resource

<string name = "welcome_messages">こんにちは%1$s!あなたが持っている%2$d新しいメッセージを</文字列>

string substitution以下のようにしてください:

getString(R.string.welcome_message、 、)。"Test"0

注意:

  • %1 $ sは文字列「Test」に置き換えられます
  • %2 $ dは文字列 "0"に置き換えられます

16

私は同じlintエラーメッセージに遭遇し、それをこの方法で解決しました。

最初は私のコードは:

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()メソッド内でテキストを連結しないでください。必要なものをストリングに連結し、そのストリング値を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));

どうして?1つは他にどのような利点がありますか?
フューリーシュ

4

問題は""、すべての文字列の先頭に追加するためです。

lintは渡される引数をスキャンしsetText、警告を生成します。この場合、次の警告が関連します。

テキストチャンクを連結してメッセージを作成しないでください。このようなメッセージは適切に翻訳できません。

すべての文字列を""

渡す引数は既にテキストであるため、この連結を削除してください。また、.toString()文字列を連結する代わりに、必要に応じて他の場所で使用することもできます""


0

i18nをサポートする必要がない場合は、Android Studioでこのlintチェックを無効にできます

ファイル->設定->エディタ->インスペクション-> Android-> Lint-> TextView Internationalization(チェックを外す)


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);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.