TextView.setTextSize si comporta in modo anomalo - Come impostare dinamicamente la dimensione del testo di textview per schermi diversi


119

La chiamata TextView.setTextSize()funziona in modo anomalo. Subito dopo la chiamata a, setTextSizese otteniamo un, getTextSizerestituisce un valore molto più alto di quello che abbiamo impostato in precedenza.

Ecco cosa stiamo facendo:

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

Qualcuno l'ha visto prima?


2
Stai ottenendo e impostando la dimensione del testo su due oggetti diversi?
Cheryl Simon

Risposte:


359

La differenza qui è che nel setTextSize(int size)metodo, il tipo di unità di default è "sp" o "pixel scalati". Questo valore sarà una dimensione in pixel diversa per ciascuna densità dello schermo (ldpi, mdpi, hdpi).

getTextSize(), d'altra parte, restituisce le dimensioni effettive in pixel del testo.

È possibile utilizzare setTextSize(int unit, float size)per specificare un tipo di unità. I valori costanti per questo possono essere trovati nella classe TypedValue, ma alcuni di essi sono:

TypedValue.COMPLEX_UNIT_PX   //Pixels

TypedValue.COMPLEX_UNIT_SP   //Scaled Pixels

TypedValue.COMPLEX_UNIT_DIP  //Device Independent Pixels

L'ho appena trovato e stavo per pubblicarlo qui. Molte grazie!
singhspk

1
Penso che dovrebbe effettivamente da TypedValue (singolare). L'importazione è android.util.TypedValue;
Hein du Plessis

5
Inoltre da notare, ha iniziato a farlo solo al livello API 7. Un altro "gotcha" in una ridicola API.
mxcl

3
È importante fare attenzione all'ordine degli argomenti: ho accidentalmente impostato setTextSize (size, TypedValue.COMPLEX_UNIT_SP) perché era l'ordine che avevo erroneamente presunto!
Mark

1
È interessante notare che su ICS sul mio Galaxy Nexus, l'utilizzo di setTextSize (14, TypedValue.COMPLEX_UNIT_SP) non ha avuto alcun effetto (quindi ho utilizzato la dimensione predefinita), ma quando ho aggiornato a Jelly Bean, non è stato visualizzato alcun testo (come la dimensione 0). Stavo per segnalare un bug di Jelly Bean quando ho capito il mio errore!
Mark

20

questo problema si è verificato perché il getTextSize()metodo restituisce la dimensione in pixel dipende dalla densità dello schermo! per ottenere la dimensione effettiva del testo usa questo:

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

spero che lo risolva :)


2
Ho risolto il mio problema utilizzando le metriche di visualizzazione con setTextSize(int unit, float size)
Edward Chiang

8

se l'impostazione cambia la dimensione del carattere , qualcosa causa un errore di visualizzazione , puoi fare come :

setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15.f);

3
Chi imposta textSize in DIP?
IgorGanapolsky

4

Quando proviamo a impostareText () programmaticamente problema con getTextSize (), restituisce il valore in px invece di sp / dp / dip e sappiamo 1sp / dp = 1.5px (dimensione dello schermo = 240).

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

funziona perfettamente per me o possiamo usare displaymatrix per px: rapporto sp / dp quindi sostituire quel valore con 1.5f

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

3

Dopo molto tempo ha colpito questo e finalmente risolto così

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

crea una cartella dimen come questa res / values ​​/ dimension.xml

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

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

 </resources>

2

In breve, se vuoi ridurre la dimensione del testo

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

Poiché getTextSize () restituisce UNIT_PX, allora dovremmo usare UNIT_PX


1

Soluzione Kotlin

Per impostare l'utilizzo di una risorsa, usa semplicemente questo:

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

Per fare lo stesso con un valore di risorsa, aggiungi questa proprietà di estensione per impostare molto più facilmente la dimensione del testo

textView.textSizeRes = R.dimen.my_text_size

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

0

Aggiungendo un po 'di sapore in più a questa risposta, ho anche incappato in un po' di confusione. Si dovrebbe essere in grado di rilasciare questo test a qualsiasi @RunWith(AndroidJUnit4.class)prova che avete nel vostro progetto (avrete anche bisogno di aggiungere le dimens al vostro dimens.xml).

Nota: tutti questi test vengono superati

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

Il grande risultato che ho trovato è che TextView.setTextSize(float) applica il ridimensionamento del carattere , quindi se passi a un dimen che è già etichettato come SP invece di DP, riceverà il ridimensionamento del carattere due volte .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.