J'ai donc Android 2.3.5 appareil qui est NORMAL/HDPI. J'ai un dimens.xml dans mon projet:
...
<dimen name="gameresult_congrats_label_msg_textSize">20sp</dimen>
...
ce fichier est absolument identique dans les dossiers values-normal/values-hdpi et ainsi de suite. Dans ma première application d'activité, je montre cette valeur en utilisant:
Toast.makeText(this, "textSize is "+getResources().getDimensionPixelSize(R.dimen.gameresult_congrats_label_msg_textSize), Toast.LENGTH_SHORT).show();
et il affiche 30. J'ai également essayé:
Toast.makeText(this, "textSize is "+getResources().getDimension(R.dimen.gameresult_congrats_label_msg_textSize), Toast.LENGTH_SHORT).show();
mais le résultat est le même. Mais seulement quand j'ai essayé ceci:
Toast.makeText(this, "textSize is "+getResources().getString(R.dimen.gameresult_congrats_label_msg_textSize), Toast.LENGTH_SHORT).show();
J'ai enfin mon "20sp"! Mais pourquoi ça? Les documents officiels disent que ces méthodes renvoie
Valeur de dimension de ressource multipliée par la mesure appropriée.
J'ai vérifié cela en modifiant ma valeur à 25 et j'ai obtenu 38, ce qui signifie que aos utilise un multiplicateur de 1,5. Mais pourquoi? Il obtient déjà de la valeur à partir du dossier approprié, ce qui signifie qu'il obtient une valeur prête à l'emploi! D'où aos obtient ce multiplicateur 1,5x? Je sais que cela dépend de DisplayMetrics. Mais comment il calcule 1,5x?
[~ # ~] mise à jour [~ # ~]
Je comprends le multiplicateur mais, voyez-vous, le vrai problème ici concerne la double mise à l'échelle. Et c'est pourquoi j'ai posé cette question.
Donc, si j'ai du layout.xml (dans le dossier res\layout) avec TexView défini comme:
<TextView
Android:id="@+id/congratsLabel"
...
Android:textSize="@dimen/gameresult_congrats_label_msg_textSize" />
Tout semble correct. Je veux dire que textview est comme je m'y attendais.
Maintenant, faisons de même dans le code:
TextView congratsLabel = fineViewById(R.id.congratsLabel);
textSize = getResources().getDimension(R.dimen.gameresult_congrats_label_msg_textSize)
congratsLabel.setTextSize(textSize)
et voici le problème !!! getResources (). getDimension () renvoie une valeur [~ # ~] mise à l'échelle [~ # ~] et c'est ok. Mais la taille résultante de mon textView sera 1,5 plus grande que ce à quoi je m'attendais parce que setTextSize fonctionne avec SP et voici la deuxième échelle! Et c'est pourquoi AOS fait que la taille du texte résultant est réduite à 45 (initialement définie comme 20sp).
Selon la formation prenant en charge différentes densités d'écran , hdpi est de taille normale 1,5x (mdpi). Comme getDimensionPixelSize
prend en compte cette différence lors de la conversion en pixels, la valeur renvoyée sera 1,5 fois votre valeur dans sp
.
Notez que sp
dépend également de la taille de texte préférée de l'utilisateur et peut donc changer pour être encore plus grand que 1,5 fois votre valeur attendue.
Juste pour clarifier (informations obtenues en inspectant Android):
Resources.getDimension()
et getDimensionPixelOffset()
/getDimensionPixelSize()
ne diffèrent que par le fait que le premier renvoie float
tandis que les deux derniers renvoient la même valeur arrondie à int
convenablement. Pour chacun d'eux, la valeur de retour est en pixels bruts.
Les trois fonctions sont implémentées en appelant Resources.getValue()
et en convertissant le TypedValue
ainsi obtenu en appelant TypedValue.complexToDimension()
, TypedValue.complexToDimensionPixelOffset()
et TypedValue.complexToDimensionPixelSize()
, respectivement.
Par conséquent, si vous souhaitez obtenir la valeur "brute" avec l'unité spécifiée dans la source XML, appelez Resources.getValue()
et utilisez les méthodes de la classe TypedValue
.
La méthode getDimension () convertit les valeurs dp ou sp en pixels en fonction de la densité d'écran actuelle. Ceci est très utile car vous n'avez pas à le faire vous-même, lorsque vous souhaitez définir la largeur ou la taille du texte Java Java (ils n'acceptent que les pixels).
Mais si vous avez besoin de sp ou dp d'origine, vous pouvez faire du "reverse engineering".
Étape 1. Vérifier le rapport d'échelle actuel (basé sur la densité de l'écran):
float scaleRatio = getResources().getDisplayMetrics().density;
Étape 2. Obtenez la dimension de dimens.xml
float dimenPix = getResources().getDimension(R.dimen.your_dimen_name);
Étape 3. Faites quelques calculs
float dimenOrginal = dimenPix/scaleRatio;
Remarques:
En savoir plus sur les dimensions dans Android: http://Android4beginners.com/2013/07/appendix-c-everything-about-sizes-and-dimensions-in-Android/
Si quelqu'un d'autre en a besoin:
Pour résoudre le problème de double mise à l'échelle Stan affiche lors de l'utilisation de getDimensionPixelSize avec TextView.setTextSize:
Vous pouvez utiliser la version alternative de setTextSize où vous pouvez spécifier l'unité comme ceci:
title.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen.title));
Parce que ... NORMAL n'est PAS hdpi ...
Normal est mdpi (160dpi) = 1,0x.
hdpi (240 dpi) est 1,5x.
xhdpi (320dpi) est 2,0x.
xxdpi (480dpi) est 3.0x.
xxxhdpi (640dpi) est 4,0x.
Et (dernier point, mais non des moindres), ldpi (120 dpi) est de 0,75x.