J'ai créé mon application avec la hauteur et la largeur en pixels pour un appareil Pantech dont la résolution est de 480x800.
J'ai besoin de convertir la hauteur et la largeur d'un appareil G1. Je pensais que le convertir en dp résoudrait le problème et fournirait la même solution pour les deux appareils.
Y a-t-il un moyen facile de convertir des pixels en dp? Aucune suggestion?
// Converts 14 dip into its equivalent px
float dip = 14f;
Resources r = getResources();
float px = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dip,
r.getDisplayMetrics()
);
/**
* This method converts dp unit to equivalent pixels, depending on device density.
*
* @param dp A value in dp (density independent pixels) unit. Which we need to convert into pixels
* @param context Context to get resources and device specific display metrics
* @return A float value to represent px equivalent to dp depending on device density
*/
public static float convertDpToPixel(float dp, Context context){
return dp * ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}
/**
* This method converts device specific pixels to density independent pixels.
*
* @param px A value in px (pixels) unit. Which we need to convert into db
* @param context Context to get resources and device specific display metrics
* @return A float value to represent dp equivalent to px value
*/
public static float convertPixelsToDp(float px, Context context){
return px / ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}
De préférence dans une classe Util.Java
public static float dpFromPx(final Context context, final float px) {
return px / context.getResources().getDisplayMetrics().density;
}
public static float pxFromDp(final Context context, final float dp) {
return dp * context.getResources().getDisplayMetrics().density;
}
float density = context.getResources().getDisplayMetrics().density;
float px = someDpValue * density;
float dp = somePxValue / density;
density
est égal à
.75
sur ldpi
(120
dpi) 1.0
sur mdpi
(160
dpi; baseline)1.5
sur hdpi
(240
dpi)2.0
sur xhdpi
(320
dpi) 3.0
sur xxhdpi
(480
dpi) 4.0
sur xxxhdpi
(640
dpi) Utilisez ce convertisseur online pour jouer avec les valeurs dpi.
EDIT: Il semble qu’il n’y ait aucune relation 1: 1 entre dpi
bucket et density
. Il semble que le Nexus 5X
étant xxhdpi
ait une valeur density
de 2.625
(au lieu de 3
). Voyez vous-même dans les métriques Device .
Si vous pouvez utiliser les dimensions XML, c'est très simple!
Dans votre res/values/dimens.xml
:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="thumbnail_height">120dp</dimen>
...
...
</resources>
Puis dans votre Java:
getResources().getDimensionPixelSize(R.dimen.thumbnail_height);
Selon le Guide de développement Android:
px = dp * (dpi / 160)
Mais souvent, vous voudrez le faire à l’inverse lorsque vous recevez un dessin libellé en pixels. Alors:
dp = px / (dpi / 160)
Si vous utilisez un périphérique de 240 dpi, ce rapport est égal à 1,5 (comme indiqué précédemment), ce qui signifie qu'une icône de 60 pixels correspond à 40 pixels dans l'application.
Vous pouvez l'utiliser .. sans contexte
public static int pxToDp(int px) {
return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}
public static int dpToPx(int dp) {
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
Comme @Stan l'a mentionné…, l'utilisation de cette approche peut poser problème si le système change de densité. Alors soyez conscient de ça!
Personnellement, j'utilise le contexte pour le faire.
Sans Context
, méthodes statiques élégantes:
public static int dpToPx(int dp)
{
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
public static int pxToDp(int px)
{
return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}
Pour DP to Pixel
Créer une valeur dans dimens.xml
<dimen name="textSize">20dp</dimen>
Obtenez cette valeur dans pixel
comme:
int sizeInPixel = context.getResources().getDimensionPixelSize(R.dimen.textSize);
Vous pouvez donc utiliser le formulateur suivant pour calculer la bonne quantité de pixels à partir d’une dimension spécifiée dans dp
public int convertToPx(int dp) {
// Get the screen's density scale
final float scale = getResources().getDisplayMetrics().density;
// Convert the dps to pixels, based on density scale
return (int) (dp * scale + 0.5f);
}
Il existe une utilisation par défaut dans le SDK Android: http://developer.Android.com/reference/Android/util/TypedValue.html
float resultPix = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,getResources().getDisplayMetrics())
Pour ceux qui utilisent Kotlin:
val Int.toPx: Int
get() = (this * Resources.getSystem().displayMetrics.density).toInt()
val Int.toDp: Int
get() = (this / Resources.getSystem().displayMetrics.density).toInt()
Usage:
64.toPx
32.toDp
Cela devrait vous donner la conversion dp en pixels:
public static int dpToPx(int dp)
{
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
Cela devrait vous donner les pixels de conversion en dp:
public static int pxToDp(int px)
{
return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}
Probablement le meilleur moyen de placer la dimension dans values / dimen est d’obtenir la dimension directement à partir de la méthode getDimension (), elle vous renverra la dimension déjà convertie en pixel.
context.getResources().getDimension(R.dimen.my_dimension)
Juste pour mieux expliquer cela,
getDimension(int resourceId)
renverra la dimension déjà convertie en pixel AS A FLOAT.
getDimensionPixelSize(int resourceId)
retournera le même mais tronqué à int, donc AS AN INTEGER.
Voir Référence Android
fun convertDpToPixel(dp: Float, context: Context): Float {
return dp * (context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
}
fun convertPixelsToDp(px: Float, context: Context): Float {
return px / (context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
}
public static float convertDpToPixel(float dp, Context context) {
return dp * ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}
public static float convertPixelsToDp(float px, Context context) {
return px / ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}
public static int dp2px(Resources resource, int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,resource.getDisplayMetrics());
}
public static float px2dp(Resources resource, float px) {
return (float) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, px,resource.getDisplayMetrics());
}
où ressource est context.getResources ().
en utilisant kotlin-extension le rend meilleur
fun Int.toPx(context: Context): Int = (this * context.resources.displayMetrics.density).toInt()
fun Int.toDp(context: Context): Int = (this / context.resources.displayMetrics.density).toInt()
UPDATE:
Parce que displayMetrics
fait partie de Ressources partagées globales , nous pouvons utiliser Resources.getSystem()
fun Int.toPx(): Int = (this * Resources.getSystem().displayMetrics.density).toInt()
fun Int.toDp(): Int = (this / Resources.getSystem().displayMetrics.density).toInt()
comme ça:
public class ScreenUtils {
public static float dpToPx(Context context, float dp) {
if (context == null) {
return -1;
}
return dp * context.getResources().getDisplayMetrics().density;
}
public static float pxToDp(Context context, float px) {
if (context == null) {
return -1;
}
return px / context.getResources().getDisplayMetrics().density;
}
}
dépendant du contexte, retourne la valeur float, méthode statique
Si vous développez une application critique en termes de performances, veuillez considérer la classe optimisée suivante:
public final class DimensionUtils {
private static boolean isInitialised = false;
private static float pixelsPerOneDp;
// Suppress default constructor for noninstantiability.
private DimensionUtils() {
throw new AssertionError();
}
private static void initialise(View view) {
pixelsPerOneDp = view.getResources().getDisplayMetrics().densityDpi / 160f;
isInitialised = true;
}
public static float pxToDp(View view, float px) {
if (!isInitialised) {
initialise(view);
}
return px / pixelsPerOneDp;
}
public static float dpToPx(View view, float dp) {
if (!isInitialised) {
initialise(view);
}
return dp * pixelsPerOneDp;
}
}
float scaleValue = getContext().getResources().getDisplayMetrics().density;
int pixels = (int) (dps * scaleValue + 0.5f);
Voici comment cela fonctionne pour moi:
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int h = displaymetrics.heightPixels;
float d = displaymetrics.density;
int heightInPixels=(int) (h/d);
Vous pouvez faire la même chose pour la largeur.
Approche plus élégante en utilisant la fonction d'extension de Kotlin
/**
* Converts dp to pixel
*/
val Int.dpToPx: Int get() = (this * Resources.getSystem().displayMetrics.density).toInt()
/**
* Converts pixel to dp
*/
val Int.pxToDp: Int get() = (this / Resources.getSystem().displayMetrics.density).toInt()
Usage:
println("16 dp in pixel: ${16.dpToPx}")
println("16 px in dp: ${16.pxToDp}")
Vous devriez utiliser dp comme vous le feriez en pixels. C'est tout ce qu'ils sont; afficher des pixels indépendants. Utilisez les mêmes chiffres que sur un écran de densité moyenne et la taille sera magiquement correcte sur un écran de densité élevée.
Cependant, il semble que vous ayez besoin de l'option fill_parent dans votre schéma de configuration. Utilisez fill_parent lorsque vous souhaitez que votre vue ou votre contrôle se développe sur toute la taille restante du conteneur parent.
pour convertir des pixels en dp, utilisez TypedValue .
Comme mentionné dans la documentation: Conteneur pour une valeur de données dynamiquement typée.
et utilisez la méthode applyDimension :
public static float applyDimension (int unit, float value, DisplayMetrics metrics)
qui convertit une valeur de données complexe non compressée contenant une dimension en valeur finale en virgule flottante, comme suit:
Resources resource = getResources();
float dp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, 69, resource.getDisplayMetrics());
J'espère que cela pourra aider .
Beaucoup de bonnes solutions ci-dessus. Cependant, la meilleure solution que j'ai trouvée est la conception de Google:
PX
et DP
sont différents mais similaires.
DP
est la résolution lorsque vous ne factorisez que la taille physique de l'écran. Lorsque vous utilisez DP
, votre mise en page sera adaptée à des écrans de taille similaire avec des densités pixel
différentes.
De temps en temps, vous voulez réellement pixels
cependant, et lorsque vous manipulez des dimensions dans du code, vous avez toujours affaire à de vrais pixels
, sauf si vous les convertissez.
Donc, sur un appareil Android, écran de taille normale hdpi
, 800x480 is 533x320
à DP
(je crois). Pour convertir DP
en pixels /1.5
, reconvertir *1.5
. Ceci est uniquement pour la taille d'écran et dpi
, cela changerait en fonction de la conception. Nos artistes me donnent pixels
cependant et je me convertis en DP
avec l'équation 1.5
ci-dessus.
Si vous voulez Integer values, alors, en utilisant Math.round () arrondira le flottant à l'entier le plus proche.
public static int pxFromDp(final float dp) {
return Math.round(dp * Resources.getSystem().getDisplayMetrics().density);
}
Cela fonctionne pour moi (C #):
int pixels = (int)((dp) * Resources.System.DisplayMetrics.Density + 0.5f);
kotlin
fun spToPx(ctx: Context, sp: Float): Float {
return sp * ctx.resources.displayMetrics.scaledDensity
}
fun pxToDp(context: Context, px: Float): Float {
return px / context.resources.displayMetrics.density
}
fun dpToPx(context: Context, dp: Float): Float {
return dp * context.resources.displayMetrics.density
}
Java
public static float spToPx(Context ctx,float sp){
return sp * ctx.getResources().getDisplayMetrics().scaledDensity;
}
public static float pxToDp(final Context context, final float px) {
return px / context.getResources().getDisplayMetrics().density;
}
public static float dpToPx(final Context context, final float dp) {
return dp * context.getResources().getDisplayMetrics().density;
}
Pour le code Java natif de React, il existe déjà une classe util:
import com.facebook.react.uimanager.PixelUtil;
float dp = PixelUtil.toDIPFromPixel(somePixelValue);
La meilleure réponse provient du framework Android lui-même: utilisez simplement cette égalité ...
public static int dpToPixels(final DisplayMetrics display_metrics, final float dps) {
final float scale = display_metrics.density;
return (int) (dps * scale + 0.5f);
}
(convertit dp en px)
Pour Xamarin.Android
float DpToPixel(float dp)
{
var resources = Context.Resources;
var metrics = resources.DisplayMetrics;
return dp * ((float)metrics.DensityDpi / (int)DisplayMetricsDensity.Default);
}
Rendre ceci non statique est nécessaire lorsque vous créez un moteur de rendu personnalisé