TextView.setTextSize ведет себя ненормально - Как установить размер текста в текстовом виде динамически для разных экранов


120

Звонок TextView.setTextSize()работает ненормально. Сразу после вызова, setTextSizeесли мы получаем, он getTextSizeвозвращает гораздо более высокое значение, чем то, что мы установили ранее.

Вот что мы делаем:

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

Кто-нибудь видел это раньше?


2
Вы получаете и устанавливаете размер текста на двух разных объектах?
Шерил Саймон

Ответы:


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. Еще одна «ловушка» в нелепом API.
mxcl

3
Важно следить за порядком аргументов - я случайно выбрал setTextSize (size, 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)
Эдвард Чианг


4

Когда мы пытаемся программно решить проблему setText () с getTextSize (), возвращает значение в пикселях вместо 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, а затем заменить это значение на 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 ​​/ sizes.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)тест, который есть в вашем проекте (вам также нужно будет добавить размеры в свой файл sizes.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.