Android et réglage de la largeur et de la hauteur par programme en unités dp

304

Je fais:

button.setLayoutParams(new GridView.LayoutParams(65, 65));

Selon les documents, les unités de largeur et de hauteur (65 dans les deux ci-dessus) sont des "pixels". Comment forcez-vous cela à être des pixels indépendants du périphérique, ou "dp"?

SK9
la source

Réponses:

541

Vous devrez le convertir de dps en pixels en utilisant le facteur d'échelle d'affichage.

final float scale = getContext().getResources().getDisplayMetrics().density;
int pixels = (int) (dps * scale + 0.5f);
Robby Pond
la source
111
La conversion correcte est (int) (échelle dps * + 0,5f). C'est la formule que nous utilisons dans l'ensemble du cadre.
Romain Guy
8
La formule est dans les documents. Pour plus de lecture, allez à la section 3 de developer.android.com/guide/practices/…
SK9
34
@RomainGuy, pouvez-vous s'il vous plaît ajouter une fonction utilitaire à l'API pour convertir de dpà px? Merci.
AlikElzin-kilaka
3
qu'est-ce que dps ici? im obtenant l'erreur "dps ne peut pas être résolu en une variable"? quel type de "dps" devez déclarer ??
Deepak
5
La variable "dps" est la valeur d'entrée que vous souhaitez convertir.
Robby Pond,
233

Je sais que c'est une vieille question mais j'ai trouvé une façon beaucoup plus soignée de faire cette conversion.

Java

TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 65, getResources().getDisplayMetrics());

Kotlin

TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 65f, resources.displayMetrics)
drspaceboo
la source
8
Bravo pour savoir comment faire cela. Je ne suis pas fan de répéter une formule à plusieurs endroits! Merci.
darrenp
2
Sinon, créez une fonction avec la formule
Sayka
1
@Kenobi Il fait la conversion pour vous de DP en PX. Ce qui 65précède est la valeur DP que vous souhaitez convertir en PX
drspaceboo
7
Cela devrait être la réponse acceptée, pas la réponse actuelle où ces nombres (0,5) viennent magiquement de nulle part
Johny19
1
@ Johny19 Le 0,5 n'est pas magique. C'est juste comment arrondir un nombre à virgule flottante à l'entier le plus proche au lieu de le tronquer. Voir mon commentaire sur la réponse de Robby Pond pour plus de détails.
MarredCheese
38

En regardant votre besoin, il existe également une solution alternative. Il semble que vous connaissiez les dimensions en dp au moment de la compilation, vous pouvez donc ajouter une entrée dimen dans les ressources. Ensuite, vous pouvez interroger l'entrée dimen et elle sera automatiquement convertie en pixels dans cet appel:

final float inPixels= mActivity.getResources().getDimension(R.dimen.dimen_entry_in_dp);

Et votre dimens.xml aura:

<dimen name="dimen_entry_in_dp">72dp</dimen>

En étendant cette idée, vous pouvez simplement stocker la valeur de 1dp ou 1sp comme entrée dimen et interroger la valeur et l'utiliser comme multiplicateur. En utilisant cette approche, vous isolerez le code des trucs mathématiques et compterez sur la bibliothèque pour effectuer les calculs.

vigne
la source
Notez que la valeur de retour est en fait un entier, elle est donc convertie en flottant.
CorayThan
C'est une mauvaise réponse car il faut être dynamique
Johny19
37

La manière la plus simple (et fonctionne même depuis l'API 1) qui a été testée est:

getResources().getDimensionPixelSize(R.dimen.example_dimen);

Des documentations:

Récupérez une dimension pour un ID de ressource particulier pour l'utiliser comme taille en pixels bruts. C'est la même chose que getDimension (int), sauf que la valeur retournée est convertie en pixels entiers pour être utilisée comme taille. Une conversion de taille implique d'arrondir la valeur de base et de garantir qu'une valeur de base non nulle a au moins un pixel.

Oui, il arrondit la valeur mais ce n'est pas très mauvais (juste dans les valeurs impaires sur les périphériques hdpi et ldpi, il faut ajouter une petite valeur lorsque ldpi n'est pas très courant) J'ai testé dans un périphérique xxhdpi qui convertit 4dp en 16 (pixels) et c'est vrai.

David
la source