TextView.setTextSize zachowuje się nieprawidłowo - jak dynamicznie ustawić rozmiar tekstu widoku tekstu dla różnych ekranów


120

Połączenie TextView.setTextSize()działa nieprawidłowo. Zaraz po wywołaniu, setTextSizejeśli otrzymamy, getTextSizezwraca znacznie wyższą wartość niż to, na którą ustawiliśmy wcześniej.

Oto, co robimy:

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

Czy ktoś to widział wcześniej?


2
Otrzymujesz i ustawiasz rozmiar tekstu na dwóch różnych obiektach?
Cheryl Simon,

Odpowiedzi:


360

Różnica polega na tym, że w setTextSize(int size)metodzie domyślnym typem jednostki jest „sp” lub „skalowane piksele”. Ta wartość będzie mieć inny wymiar piksela dla każdej gęstości ekranu (ldpi, mdpi, hdpi).

getTextSize()z drugiej strony zwraca rzeczywiste wymiary tekstu w pikselach.

Możesz użyć setTextSize(int unit, float size)do określenia typu jednostki. Stałe wartości tego można znaleźć w klasie TypedValue, ale niektóre z nich to:

TypedValue.COMPLEX_UNIT_PX   //Pixels

TypedValue.COMPLEX_UNIT_SP   //Scaled Pixels

TypedValue.COMPLEX_UNIT_DIP  //Device Independent Pixels

Właśnie to znalazłem i zamierzałem opublikować tutaj. Wielkie dzięki!
singhspk

1
Myślę, że tak naprawdę powinno być przez TypedValue (liczba pojedyncza). Import to android.util.TypedValue;
Hein du Plessis,

5
Warto również zauważyć, że zaczął to robić dopiero na poziomie API 7. Kolejna „wpadka” w absurdalnym API.
mxcl

3
Ważne, aby uważać na kolejność argumentów - przypadkowo ustawiłem setTextSize (size, TypedValue.COMPLEX_UNIT_SP), ponieważ była to kolejność, którą błędnie założyłem!
Mark

1
Co ciekawe, na ICS na moim Galaxy Nexusie użycie setTextSize (14, TypedValue.COMPLEX_UNIT_SP) nie dało żadnego efektu (więc użyłem domyślnego rozmiaru), ale kiedy zaktualizowałem do Jelly Bean, żaden tekst nie był wyświetlany (jak rozmiar 0). Miałem właśnie zgłosić błąd Jelly Bean, kiedy zdałem sobie sprawę, że to mój błąd!
Mark

20

ten problem występuje, ponieważ getTextSize()metoda zwraca rozmiar w pikselach w zależności od gęstości ekranu! aby uzyskać rzeczywisty rozmiar tekstu, użyj tego:

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

mam nadzieję, że to rozwiąże :)


2
Rozwiązałem swój problem, używając wskaźników wyświetlania z setTextSize(int unit, float size)
Edwardem Czangiem,

8

jeśli ustawienie zmień rozmiar czcionki , coś powoduje wyświetlenie błędu , możesz zrobić jak :

setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15.f);

3
Kto ustawia textSize w DIP?
IgorGanapolsky

4

Kiedy próbujemy programowo setText () problem z getTextSize (), zwraca wartość w px zamiast sp / dp / dip i wiemy, że 1sp / dp = 1.5px (rozmiar ekranu = 240).

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

działa idealnie dla mnie lub możemy użyć współczynnika displaymatrix do px: sp / dp, a następnie zastąpić tę wartość 1,5f

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

3

Po długim czasie uderzyłem w to i ostatecznie rozwiązałem w ten sposób

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

utwórz folder dimen, taki jak ten res / values ​​/ Dimensions.xml

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

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

 </resources>

2

Krótko mówiąc, jeśli chcesz pomniejszyć rozmiar tekstu

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

Ponieważ getTextSize () zwraca UNIT_PX, powinniśmy użyć UNIT_PX


1

Rozwiązanie Kotlin

Aby ustawić użycie zasobu, po prostu użyj tego:

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

Aby zrobić to samo z wartością zasobu, dodaj tę właściwość rozszerzenia, aby znacznie łatwiej ustawić rozmiar tekstu

textView.textSizeRes = R.dimen.my_text_size

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

0

Dodanie dodatkowego smaku do tej odpowiedzi, ponieważ również wprowadziło trochę zamieszania. Państwo powinno być w stanie upuścić ten test do każdego @RunWith(AndroidJUnit4.class)testu masz w swoim projekcie (będziesz też trzeba dodać dimens do dimens.xml).

Uwaga: wszystkie te testy kończą się powodzeniem

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

Największym wnioskiem, który znalazłem, jest TextView.setTextSize(float) zastosowanie skalowania czcionki , więc jeśli podasz wymiar, który jest już oznaczony jako SP zamiast DP, otrzyma skalowanie czcionki dwukrotnie .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.