TextView.setTextSize поводиться ненормально - Як динамічно встановити розмір тексту для перегляду тексту для різних екранів


119

Виклик TextView.setTextSize()працює ненормально. Одразу після дзвінка, setTextSizeякщо ми отримаємо getTextSizeйого повернення набагато вище значення, ніж те, що ми його встановили раніше.

Ось що ми робимо:

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

Хтось бачив це раніше?


2
Ви отримуєте та встановлюєте розмір тексту на два різних об’єкти?
Шеріл Саймон

Відповіді:


359

Різниця тут полягає в тому, що в 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
Зауважимо, він почав робити це лише на рівні 7 API.
mxcl

3
Важливо стежити за порядком аргументів - я випадково встановивTextSize (size, TypedValue.COMPLEX_UNIT_SP), тому що це був порядок, який я помилково припустив!
Марк

1
Цікаво, що на ICS на моєму Galaxy Nexus, використовуючи setTextSize (14, TypedValue.COMPLEX_UNIT_SP), ефект не робився (тому використовувався типовий розмір), але коли я перейшов на Jelly Bean, жоден текст не відображався (як 0 розмір). Я ось-ось збирався повідомити про помилку Jelly Bean, коли зрозумів свою помилку!
Марк

20

ця проблема трапляється, оскільки getTextSize()метод повернення розміру в пікселях залежить від щільності екрана! щоб отримати фактичний TextSize, використовуйте це:

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

Я сподіваюся, що це вирішить :)


2
Я вирішив свою проблему, використовуючи метричні показники на екрані з setTextSize(int unit, float size)
Едвард Чіанг


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

для мене ідеально працює, або ми можемо використовувати показник matrix до px: sp / dp, а потім замінити це значення на 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));

створити папку Dim на зразок цього res / values ​​/ensions.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

Рішення Котліна

Щоб встановити за допомогою ресурсу, просто скористайтеся цим:

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

Я знайшов великий винос, який TextView.setTextSize(float) застосовує масштабування шрифту , тому, якщо ви перейдете в розмір, який вже позначений як SP замість DP, він отримає масштабування шрифту двічі .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.