TextView.setTextSize se comporta de manera anormal: cómo configurar el tamaño del texto de la vista de texto de forma dinámica para diferentes pantallas

119

La llamada TextView.setTextSize()funciona de forma anormal. Inmediatamente después de la llamada a, setTextSizesi obtenemos un, getTextSizedevuelve un valor mucho más alto que el que establecimos anteriormente.

Esto es lo que estamos haciendo:

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

¿Alguien ha visto esto antes?

singhspk
fuente
2
¿Está obteniendo y configurando el tamaño del texto en dos objetos diferentes?
Cheryl Simon

Respuestas:

359

La diferencia aquí es que en el setTextSize(int size)método, el tipo de unidad por defecto es "sp" o "píxeles escalados". Este valor será una dimensión de píxel diferente para cada densidad de pantalla (ldpi, mdpi, hdpi).

getTextSize(), por otro lado, devuelve las dimensiones reales en píxeles del texto.

Puede utilizar setTextSize(int unit, float size)para especificar un tipo de unidad. Los valores constantes para esto se pueden encontrar en la clase TypedValue, pero algunos de ellos son:

TypedValue.COMPLEX_UNIT_PX   //Pixels

TypedValue.COMPLEX_UNIT_SP   //Scaled Pixels

TypedValue.COMPLEX_UNIT_DIP  //Device Independent Pixels
Kevin Coppock
fuente
Acabo de encontrar eso y estaba a punto de publicarlo aquí. ¡Muchas gracias!
singhspk
1
Creo que debería ser por TypedValue (singular). La importación es android.util.TypedValue;
Hein du Plessis
5
También hay que tener en cuenta que solo comenzó a hacer esto en el nivel de API 7. Otro "problema" en una API ridícula.
mxcl
3
Es importante tener cuidado con el orden de los argumentos: accidentalmente había establecido un tamaño de texto (tamaño, TypedValue.COMPLEX_UNIT_SP) porque ese era el orden que supuse erróneamente.
Mark
1
Curiosamente, en ICS en mi Galaxy Nexus, usar setTextSize (14, TypedValue.COMPLEX_UNIT_SP) no tuvo ningún efecto (por lo que usé el tamaño predeterminado), pero cuando actualicé a Jelly Bean, no se mostró nada del texto (como el tamaño 0). ¡Estaba a punto de informar un error de Jelly Bean cuando me di cuenta de mi error!
Mark
20

este problema sucedió porque el getTextSize()método devuelve el tamaño en píxeles ¡depende de la densidad de la pantalla! para obtener el tamaño de texto real, use esto:

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

espero que lo resuelva :)

M_AWADI
fuente
2
Resolví mi problema usando métricas de visualización con setTextSize(int unit, float size)
Edward Chiang
8

si la configuración cambia el tamaño de la fuente, algo causa un error de visualización, puede hacer lo siguiente:

setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15.f);
hui 谁 与 争辉
fuente
3
¿Quién establece textSize DIP?
IgorGanapolsky
4

Cuando intentamos establecer un problema de programación con setText () con getTextSize (), devuelve el valor en px en lugar de sp / dp / dip y sabemos que 1sp / dp = 1.5px (tamaño de pantalla = 240).

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

funciona perfectamente para mí o podemos usar displaymatrix to px: sp / dp ratio y luego reemplazar ese valor con 1.5f

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

Después de mucho tiempo golpeó esto y finalmente resolvió así

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

crear una carpeta de dimensiones como esta res / valores / dimensiones.xml

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

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

 </resources>
NagarjunaReddy
fuente
2

En resumen, si desea reducir el tamaño de su texto

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

Debido a que getTextSize () devuelve UNIT_PX, entonces deberíamos usar UNIT_PX

Frank Nguyen
fuente
1

Solución de Kotlin

Para configurar el uso de un recurso, simplemente use esto:

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

Para hacer lo mismo con un valor de recurso, agregue esta propiedad de extensión para establecer mucho más fácilmente el tamaño de su texto

textView.textSizeRes = R.dimen.my_text_size

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

Agregar un poco de sabor adicional a esta respuesta, ya que también generó un poco de confusión. Usted debe ser capaz de soltar esta prueba en ninguna @RunWith(AndroidJUnit4.class)prueba de que tiene en su proyecto (que también tendrá que añadir los Dimens a su dimens.xml).

Nota: todas estas pruebas pasan

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

La gran conclusión que encontré es que TextView.setTextSize(float) aplica la escala de fuente , por lo que si pasa una dimensión que ya está etiquetada como SP en lugar de DP, recibirá la escala de fuente dos veces .

Kevin Grant
fuente