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?

singhspk
źródło
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
Kevin Coppock
źródło
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 :)

M_AWADI
źródło
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);
hui 谁 与 争辉
źródło
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));
ranjan
źródło
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>
NagarjunaReddy
źródło
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

Frank Nguyen
źródło
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))
    }
Gibolt
źródło
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 .

Kevin Grant
źródło