Android TextView:“ อย่าเชื่อมต่อข้อความที่แสดงด้วย setText”


148

ฉันตั้งค่าข้อความโดยใช้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:

  • อย่าโทรไปที่ Number # toString () เพื่อจัดรูปแบบตัวเลข มันจะไม่จัดการตัวคั่นเศษส่วนและตัวเลขเฉพาะสถานที่อย่างถูกต้อง พิจารณาใช้รูปแบบ String # ที่มีข้อกำหนดรูปแบบที่เหมาะสม (% d หรือ% f) แทน
  • อย่าส่งผ่านสตริงลิเทอรัล (เช่น "สวัสดี") เพื่อแสดงข้อความ ข้อความฮาร์ดโค้ดไม่สามารถแปลเป็นภาษาอื่นได้อย่างถูกต้อง ลองใช้สตริงทรัพยากรของ Android แทน
  • อย่าสร้างข้อความด้วยการต่อส่วนข้อความ ข้อความดังกล่าวไม่สามารถแปลได้อย่างถูกต้อง

ฉันทำอะไรได้บ้าง? ใครก็ได้ช่วยอธิบายว่าของคืออะไรและควรทำอย่างไร?


1
นั่นหมายความว่าคุณควรผ่านStringเข้าไปsetText()เท่านั้น เช่นsetText(name)แทนsetText("" + name). เพราะถ้าคุณเชื่อมข้อความเข้าด้วยกันมันจะไม่ถูกแปลเหมือนคุณใช้ Hardcoded text ตามที่ข้อความแจ้ง
Mr Neo

แต่จะให้NPEถ้าnameเป็นNULL
Pratik Butani

ตรวจสอบnameไม่ได้NULLก่อนใช้setText()ฟังก์ชัน
Mr Neo

3
คุณไม่ควรต่อทรัพยากร 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

คำตอบ:


308

ทรัพยากรมี 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 สามารถจัดการกับค่า null ได้ หากชื่อเป็นโมฆะจะไม่มีการวาดข้อความ


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

มันอยู่ในส่วนที่สองของคำตอบ ดู
Blackbelt

1
ฉันต้องการแสดงจำนวนเต็ม. String คือ $ s และทศนิยม $ d จำนวนเต็มย่อมาจากอะไร?
reegan29

หากคุณหมายถึง "ตัวยึดตำแหน่ง" ที่คุณสามารถ%1$dใช้ได้ @ reegan29
Blackbelt

3
สำหรับใครที่กำลังมองหา API ที่แสดงรายการประเภทของรูปแบบ: developer.android.com/reference/java/util/Formatter#syntax
Brent Sandstrom

36

อย่าสับสนกับ % 1 $ sและ% 2 $ dในคำตอบที่ยอมรับนี่คือข้อมูลเพิ่มเติมบางส่วน

  • ตัวระบุรูปแบบสามารถเป็นไวยากรณ์ต่อไปนี้:

% [ argument_index$]format_specifier

  1. อาร์กิวเมนต์ที่เป็นทางเลือกระบุเป็นตัวเลขที่ลงท้ายด้วย“ $” หลัง“%” และเลือกอาร์กิวเมนต์ที่ระบุในรายการอาร์กิวเมนต์ อาร์กิวเมนต์แรกอ้างอิงโดย"1 $"อันที่สองโดย"2 $"เป็นต้น
  2. ตัวระบุรูปแบบที่ต้องการคืออักขระที่ระบุว่าควรจัดรูปแบบอาร์กิวเมนต์อย่างไร ชุดของการแปลงที่ถูกต้องสำหรับอาร์กิวเมนต์ที่กำหนดขึ้นอยู่กับประเภทข้อมูลของอาร์กิวเมนต์

ตัวอย่าง

เราจะสร้างสตริงที่จัดรูปแบบต่อไปนี้โดยที่แทรกส่วนสีเทาโดยทางโปรแกรม

สวัสดีครับTest! คุณมี0ข้อความใหม่

ของคุณstring resource:

<string name = "welcome_messages"> สวัสดี%1$s! คุณมี%2$dข้อความใหม่ </ string>

ทำstring substitutionตามที่ระบุด้านล่าง:

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

บันทึก:

  • % 1 $ s จะถูกแทนที่ด้วยสตริง "Test"
  • % 2 $ d จะถูกแทนที่ด้วยสตริง "0"

17

ฉันพบข้อความแสดงข้อผิดพลาดผ้าสำลีเดียวกันและแก้ไขด้วยวิธีนี้

ตอนแรกรหัสของฉันคือ:

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

หลังจากนี้ข้อผิดพลาดของฉันก็หายไป พฤติกรรมในแอพไม่เปลี่ยนแปลงและปริมาณของฉันยังคงแสดงต่อไปตามที่ฉันต้องการในตอนนี้โดยไม่มีข้อผิดพลาดที่เป็นขุย


11

อย่าต่อข้อความภายในเมธอด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

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

4

ปัญหาเกิดจากคุณต่อท้าย""ทุกสตริง

ผ้าสำลีจะสแกนอาร์กิวเมนต์ที่ส่งผ่านไปsetTextและจะสร้างคำเตือนในกรณีของคุณคำเตือนต่อไปนี้เกี่ยวข้อง:

อย่าสร้างข้อความด้วยการต่อส่วนข้อความ ข้อความดังกล่าวไม่สามารถแปลได้อย่างถูกต้อง

""ขณะที่คุณกำลังเชื่อมโยงกับทุกสตริง

ลบการเชื่อมต่อนี้ออกเนื่องจากอาร์กิวเมนต์ที่คุณส่งผ่านเป็นข้อความแล้ว นอกจากนี้คุณสามารถใช้.toString()ถ้าจำเป็นที่อื่นแทนการเชื่อมสตริงของคุณเข้าด้วยกัน""


1

อย่าบ้าง่ายเกินไป

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

0

หากคุณไม่ต้องการรองรับ i18n คุณสามารถปิดการตรวจสอบผ้าสำลีนี้ได้ใน Android Studio

File -> Settings -> Editor -> Inspections -> Android -> Lint -> TextView Internationalization (ยกเลิกการเลือกนี้)



0
prodNameView.setText("" + name); //this produce lint error

val nameStr="" + name;//workaround for quick warning fix require rebuild
prodNameView.setText(nameStr);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.