TextView.setTextSize se comporte anormalement - Comment définir la taille du texte de la vue de texte de manière dynamique pour différents écrans

120

L'appel TextView.setTextSize()fonctionne anormalement. Juste après l'appel à setTextSizesi nous obtenons un getTextSizeson, il renvoie une valeur beaucoup plus élevée que celle que nous lui avons définie plus tôt.

Voici ce que nous faisons:

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

Quelqu'un a-t-il déjà vu cela avant?

singhspk
la source
2
Vous obtenez et définissez la taille du texte sur deux objets différents?
Cheryl Simon

Réponses:

360

La différence ici est que dans la setTextSize(int size)méthode, le type d'unité par défaut est "sp" ou "pixels mis à l'échelle". Cette valeur sera une dimension de pixel différente pour chaque densité d'écran (ldpi, mdpi, hdpi).

getTextSize(), d'autre part, renvoie les dimensions réelles en pixels du texte.

Vous pouvez utiliser setTextSize(int unit, float size)pour spécifier un type d'unité. Les valeurs constantes pour cela peuvent être trouvées dans la classe TypedValue, mais certaines d'entre elles sont:

TypedValue.COMPLEX_UNIT_PX   //Pixels

TypedValue.COMPLEX_UNIT_SP   //Scaled Pixels

TypedValue.COMPLEX_UNIT_DIP  //Device Independent Pixels
Kevin Coppock
la source
Je viens de le trouver et j'étais sur le point de le publier ici. Merci beaucoup!
singhspk
1
Je pense qu'il devrait en fait par TypedValue (singulier). L'importation est android.util.TypedValue;
Hein du Plessis
5
A noter également, il n'a commencé à faire cela qu'au niveau de l'API 7. Un autre «piège» dans une API ridicule.
mxcl le
3
Il est important de faire attention à l'ordre des arguments - j'ai accidentellement eu setTextSize (size, TypedValue.COMPLEX_UNIT_SP) parce que c'était l'ordre que je présumais par erreur!
Mark
1
Fait intéressant, sur ICS sur mon Galaxy Nexus, l'utilisation de setTextSize (14, TypedValue.COMPLEX_UNIT_SP) n'a fait aucun effet (donc utilisé la taille par défaut), mais lorsque j'ai mis à niveau vers Jelly Bean, aucun texte n'a été affiché (comme la taille 0). J'étais sur le point de signaler un bug Jelly Bean quand j'ai réalisé mon erreur!
Mark le
20

ce problème est survenu car la getTextSize()méthode renvoie la taille en pixels dépend de la densité de l'écran! pour obtenir la taille réelle du texte, utilisez ceci:

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

j'espère que ça résoudra :)

M_AWADI
la source
2
J'ai résolu mon problème en utilisant des métriques d'affichage avec setTextSize(int unit, float size)
Edward Chiang
8

si le réglage change la taille de la police , quelque chose cause une erreur d'affichage , vous pouvez faire comme :

setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15.f);
hui 谁 与 争辉
la source
3
Qui définit textSize DIP?
IgorGanapolsky
4

Lorsque nous essayons de régler un problème par programme avec getTextSize (), renvoie la valeur en px au lieu de sp / dp / dip et nous savons 1sp / dp = 1.5px (taille de l'écran = 240).

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

fonctionne parfaitement pour moi ou nous pouvons utiliser le rapport displaymatrix en px: sp / dp puis remplacer cette valeur par 1,5f

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

Après avoir longtemps frappé cela et finalement résolu comme ça

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

créer un dossier dimen comme celui-ci res / values ​​/ dimensions.xml

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

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

 </resources>
NagarjunaReddy
la source
2

En bref, si vous souhaitez réduire la taille de votre texte

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

Parce que getTextSize () retourne UNIT_PX, alors nous devrions utiliser UNIT_PX

Frank Nguyen
la source
1

Solution Kotlin

Pour définir à l'aide d'une ressource, utilisez simplement ceci:

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

Pour faire de même avec une valeur de ressource, ajoutez cette propriété d'extension pour définir beaucoup plus facilement la taille de votre texte

textView.textSizeRes = R.dimen.my_text_size

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

Ajouter une saveur supplémentaire à cette réponse, car cela a également entraîné un peu de confusion. Vous devriez pouvoir déposer ce test dans n'importe quel @RunWith(AndroidJUnit4.class)test que vous avez dans votre projet (vous devrez également ajouter les dimens à votre dimens.xml).

Remarque: tous ces tests réussissent

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

Le gros avantage que j'ai trouvé est que l' TextView.setTextSize(float) application de la mise à l'échelle de la police , donc si vous passez dans une dimension qui est déjà étiquetée SP au lieu de DP, elle recevra la mise à l'échelle de la police deux fois .

Kevin Grant
la source