TextView.setTextSize ทำงานผิดปกติ - วิธีตั้งค่าขนาดตัวอักษรของ textview แบบไดนามิกสำหรับหน้าจอต่างๆ


120

การโทรTextView.setTextSize()ทำงานผิดปกติ ทันทีหลังจากการเรียกไปที่setTextSizeว่าเราได้รับค่าที่getTextSizeส่งคืนมากว่าสิ่งที่เราตั้งไว้ก่อนหน้านี้

นี่คือสิ่งที่เรากำลังทำ:

zoomControl.setOnZoomInClickListener(new OnClickListener() {
    public void onClick(View view) {
        float size = mViewShabad.getTextSize() + 1;
        textView.setTextSize(size);
    }
});

มีใครเห็นสิ่งนี้มาก่อนหรือไม่?


2
คุณกำลังรับและกำหนดขนาดตัวอักษรบนวัตถุสองชิ้นที่แตกต่างกัน
Cheryl Simon

คำตอบ:


360

ความแตกต่างคือในsetTextSize(int size)วิธีนี้ประเภทหน่วยโดยค่าเริ่มต้นคือ "sp" หรือ "พิกเซลที่ปรับขนาด" ค่านี้จะเป็นขนาดพิกเซลที่แตกต่างกันสำหรับความหนาแน่นของหน้าจอแต่ละรายการ (ldpi, mdpi, hdpi)

getTextSize()ในทางกลับกันส่งกลับขนาดพิกเซลจริงของข้อความ

คุณสามารถใช้setTextSize(int unit, float size)เพื่อระบุประเภทหน่วย ค่าคงที่สำหรับสิ่งนี้สามารถพบได้ในคลาส TypedValue แต่ค่าบางส่วน ได้แก่ :

TypedValue.COMPLEX_UNIT_PX   //Pixels

TypedValue.COMPLEX_UNIT_SP   //Scaled Pixels

TypedValue.COMPLEX_UNIT_DIP  //Device Independent Pixels

ฉันเพิ่งค้นพบและกำลังจะโพสต์ไว้ที่นี่ ขอบคุณมาก!
singhspk

1
ฉันคิดว่ามันควรจะเป็น TypedValue (เอกพจน์) การนำเข้าคือ android.util.TypedValue;
Hein du Plessis

5
นอกจากนี้โปรดทราบว่ามันเริ่มทำสิ่งนี้ที่ API ระดับ 7 เท่านั้น "gotcha" อีกตัวใน API ที่ไร้สาระ
mxcl

3
สิ่งสำคัญที่ต้องระวังลำดับอาร์กิวเมนต์ - ฉันบังเอิญมี setTextSize (ขนาด, TypedValue.COMPLEX_UNIT_SP) เพราะนั่นเป็นคำสั่งที่ฉันเข้าใจผิด!
ทำเครื่องหมาย

1
ที่น่าสนใจบน ICS บน Galaxy Nexus ของฉันโดยใช้ setTextSize (14, TypedValue.COMPLEX_UNIT_SP) ไม่มีผลใด ๆ (จึงใช้ขนาดเริ่มต้น) แต่เมื่อฉันอัปเกรดเป็น Jelly Bean ไม่มีข้อความใดปรากฏขึ้น (เช่นขนาด 0) ฉันเพิ่งจะรายงานข้อผิดพลาดของ Jelly Bean เมื่อฉันตระหนักถึงความผิดพลาด!
ทำเครื่องหมาย

20

ปัญหานี้เกิดขึ้นเนื่องจากgetTextSize()วิธีการคืนขนาดเป็นพิกเซลขึ้นอยู่กับความหนาแน่นของหน้าจอ! เพื่อรับขนาดข้อความจริงให้ใช้สิ่งนี้:

DisplayMetrics metrics;
metrics = getApplicationContext().getResources().getDisplayMetrics();
float Textsize =myTextView.getTextSize()/metrics.density;
myTextView.setTextSize(Textsize+1);

ฉันหวังว่ามันจะแก้ปัญหาได้ :)


2
ฉันแก้ปัญหาของฉันโดยใช้เมตริกการแสดงผลกับsetTextSize(int unit, float size)
Edward Chiang

8

หากการตั้งค่าเปลี่ยนขนาดตัวอักษร, ทำให้เกิดข้อผิดพลาดบางอย่าง, คุณสามารถทำได้ดังนี้:

setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15.f);

3
ใครกำหนด textSize ในDIP?
IgorGanapolsky

4

เมื่อเราพยายาม setText () ปัญหาทางโปรแกรมด้วย getTextSize () ให้ส่งคืนค่าเป็น px แทน sp / dp / dip และเรารู้ว่า 1sp / dp = 1.5px (ขนาดหน้าจอ = 240)

 titleBar.setTextSize(TypedValue.COMPLEX_UNIT_SP, (getResources().getDimension(R.dimen.text_size)*1.5f)); 

ทำงานได้อย่างสมบูรณ์แบบสำหรับฉันหรือเราสามารถใช้ displaymatrix เป็น px: sp / dp ratio จากนั้นแทนที่ค่านั้นด้วย 1.5f

means-> titleBar.setTextSize(TypedValue.COMPLEX_UNIT_SP, (getResources().getDimension(R.dimen.text_size)*your_sp_and_px_ratio_in_int f));

3

หลังจากหลงเรื่องนี้มานานและสุดท้ายก็แก้ไขเช่นนี้

textView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
          getResources().getDimension(R.dimen.textsize));

สร้างโฟลเดอร์ dimen เช่นนี้ res / values ​​/ dimension.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

 <dimen name="textsize">8sp</dimen>

 </resources>

2

ในระยะสั้นหากคุณต้องการย่อขนาดตัวอักษร

float size = mViewShabad.getTextSize()*1.1f;
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);

เนื่องจาก getTextSize () ส่งคืน UNIT_PX เราจึงควรใช้ UNIT_PX


1

โซลูชัน Kotlin

ในการตั้งค่าโดยใช้ทรัพยากรเพียงใช้สิ่งนี้:

textView.setTextSize(COMPLEX_UNIT_PX, textView.resources.getDimension(R.dimen.my_text_size))

หากต้องการทำเช่นเดียวกันกับค่าทรัพยากรให้เพิ่มคุณสมบัติส่วนขยายนี้เพื่อกำหนดขนาดข้อความของคุณได้ง่ายขึ้นมาก

textView.textSizeRes = R.dimen.my_text_size

var TextView.textSizeRes
    get() = textSize.toInt()
    set(@DimenRes textSizeRes) {
        setTextSize(COMPLEX_UNIT_PX, resources.getDimension(textSizeRes))
    }

0

การเพิ่มรสชาติพิเศษสำหรับคำตอบนี้ในขณะเดียวกันก็เกิดความสับสนเล็กน้อย คุณควรจะวางการทดสอบนี้ลงในการทดสอบใด ๆ ที่@RunWith(AndroidJUnit4.class)คุณมีในโปรเจ็กต์ของคุณได้ (คุณจะต้องเพิ่มการหรี่ลงใน dimens.xml ของคุณด้วย)

หมายเหตุ: การทดสอบทั้งหมดนี้ผ่าน

@Test public void testScaledFontSizes() {
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
    final Context context = InstrumentationRegistry.getTargetContext();

    Configuration configuration = context.getResources().getConfiguration();
    configuration.fontScale = 2.0f;
    configuration.densityDpi = 160; // mdpi, 1:1
    context.getResources().updateConfiguration(configuration, null);

    float scaledTextSize = context.getResources().getDimensionPixelSize(R.dimen.sp_15);
    assertEquals(30.0f, scaledTextSize);

    // Create a new TextView with the explicitly set configuration
    TextView textView = new TextView(context);
    textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, scaledTextSize);

    // 30, because font size is scaled
    assertEquals(30.0f, textView.getTextSize());

    // This is what we *don't* want, it's scaled *twice*!
    textView.setTextSize(scaledTextSize);
    assertEquals(60.0f, textView.getTextSize());

    // DP instead of SP tests
    float fifteenDp = context.getResources().getDimensionPixelSize(R.dimen.dp_15);
    assertEquals(15.0f, fifteenDp);

    textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, fifteenDp);
    // Still 15, because it's DP, not SP
    assertEquals(15.0f, fifteenDp);

    textView.setTextSize(fifteenDp);
    // 30, because setTextSize DOES font scaling
    assertEquals(30.0f, textView.getTextSize());
  }
}

Takeaway ที่ใหญ่ผมพบคือว่าTextView.setTextSize(float) ใช้การปรับขนาดตัวอักษรดังนั้นหากคุณผ่านในครับ dimen ที่มีป้ายกำกับแล้วเป็น SP แทน DP แล้วมันจะได้รับการปรับขนาดตัวอักษรเป็นครั้งที่สอง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.