web-dev-qa-db-fra.com

Formule px à dp, dp à px android

J'essaie de calculer une quantité variable de pixels pour obtenir une densité de pixels indépendante et inversement.

Cette formule (px to dp): dp = (int)(px / (displayMetrics.densityDpi / 160)); ne fonctionne pas sur les petits appareils car elle est divisée par zéro.

Voici ma formule dp en px:

px = (int)(dp * (displayMetrics.densityDpi / 160));

Quelqu'un pourrait-il me donner des indications?

144
Bram

Remarque: La solution largement utilisée ci-dessus est basée sur displayMetrics.density. Cependant, la documentation explique que cette valeur est une valeur arrondie, utilisée avec les "compartiments" de l'écran. Par exemple. sur mon Nexus 10, il retourne 2, où la valeur réelle serait 298dpi (real)/160dpi (valeur par défaut) = 1.8625.

Selon vos besoins, vous aurez peut-être besoin de la transformation exacte, qui peut être réalisée comme suit:

[Modifier] Ceci n'est pas destiné à être mélangé avec l'unité de traitement de données interne d'Android, car il est bien sûr toujours basé sur les compartiments d'écran. Utilisez ceci lorsque vous voulez une unité qui devrait restituer la même taille réelle sur différents périphériques.

Convertir dp en pixel:

public int dpToPx(int dp) {
    DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
    return Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));     
}

Convertir pixel en dp:

public int pxToDp(int px) {
    DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
    return Math.round(px / (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
}

Notez qu'il existe des propriétés xdpi et ydpi, vous voudrez peut-être distinguer, mais je ne peux pas imaginer un affichage sain où ces valeurs diffèrent grandement.

310
Bachi

J'ai résolu mon problème en utilisant les formules suivantes. Puisse d'autres personnes en bénéficier.

dp à px:

displayMetrics = context.getResources().getDisplayMetrics();
return (int)((dp * displayMetrics.density) + 0.5);

px à dp:

displayMetrics = context.getResources().getDisplayMetrics();
return (int) ((px/displayMetrics.density)+0.5);
102
Bram

px à dp:

int valueInpx = ...;
int valueInDp= (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP, valueInpx , getResources()
                .getDisplayMetrics());
33
Kannan Suresh

Appelez simplement getResources().getDimensionPixelSize(R.dimen.your_dimension) pour convertir de dp unités en pixels

27
pelotasplus

Manière efficace jamais

DP en pixel:

private int dpToPx(int dp)
{
    return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}

Pixel à DP:

private int pxToDp(int px)
{
    return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}

J'espère que cela vous aidera.

27
Hiren Patel

tilisez cette fonction

private int dp2px(int dp) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
}
px = dp * (dpi / 160)

dp = px * (160 / dpi)
5
ct_rob

Dans la plupart des cas, les fonctions de conversion sont appelées fréquemment. Nous pouvons l’optimiser en ajoutant de la mémoisation. Donc, il ne calcule pas chaque fois que la fonction est appelée.

Déclarons un HashMap qui stockera les valeurs calculées.

private static Map<Float, Float> pxCache = new HashMap<>();

Une fonction qui calcule les valeurs de pixel:

public static float calculateDpToPixel(float dp, Context context) {

        Resources resources = context.getResources();
        DisplayMetrics metrics = resources.getDisplayMetrics();
        float px = dp * (metrics.densityDpi / 160f);
        return px;

    }

Une fonction de mémorisation qui renvoie la valeur de HashMap et conserve l’enregistrement des valeurs précédentes.

La mémorisation peut être implémentée de différentes manières en Java. Pour Java 7:

public static float convertDpToPixel(float dp, final Context context) {

        Float f = pxCache.get(dp);
        if (f == null) {
            synchronized (pxCache) {
                f = calculateDpToPixel(dp, context);
                pxCache.put(dp, f);
            }

        }

        return f;
    }

Java 8 supporte la fonction Lambda:

public static float convertDpToPixel(float dp, final Context context) {

        pxCache.computeIfAbsent(dp, y ->calculateDpToPixel(dp,context));
}

Merci.

3
Parth mehta

Les fonctions ci-dessous ont bien fonctionné pour moi sur tous les appareils.

Il est tiré de https://Gist.github.com/laaptu/7867851

public static float convertPixelsToDp(float px){
    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
    float dp = px / (metrics.densityDpi / 160f);
    return Math.round(dp);
}

public static float convertDpToPixel(float dp){
    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
    float px = dp * (metrics.densityDpi / 160f);
    return Math.round(px);
}
2
Blesson Jose
2
KMI

Vous pouvez utiliser [DisplayMatrics][1] et déterminer la densité de l'écran. Quelque chose comme ça:

int pixelsValue = 5; // margin in pixels
float d = context.getResources().getDisplayMetrics().density;
int margin = (int)(pixelsValue * d);

Si je me souviens bien, il est préférable d'utiliser un revêtement de sol pour les décalages et un arrondi pour les largeurs.

1
Houcine

// pour obtenir des valeurs décimales/flottantes

public static float convertPixelsToDp(float px, Context context) {

    Resources resources = context.getResources();
    DisplayMetrics metrics = resources.getDisplayMetrics();
    float dp = px / (metrics.densityDpi / 160f);
    return Math.round(dp);
}



public static float convertDpToPixel(float dp, Context context) {
    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
    float px = dp * (metrics.densityDpi / 160f);
    return Math.round(px);
}


// for  getting in terms of Integer

private int convertPxToDp(int px, Context context) {
    Resources resources = context.getResources();
    return Math.round(px / (resources.getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
}


private int convertDpToPx(int dp, Context context) {
    Resources resources = context.getResources();

    return Math.round(dp * (resources.getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));

}

______________________________________________________________________________

public static float convertPixelsToDp(float px){
    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
    float dp = px / (metrics.densityDpi / 160f);
    return Math.round(dp);
}

public static float convertDpToPixel(float dp){
    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
    float px = dp * (metrics.densityDpi / 160f);
    return Math.round(px);
}


private int convertDpToPx(int dp){
    return Math.round(dp*(getResources().getDisplayMetrics().xdpi/DisplayMetrics.DENSITY_DEFAULT));

}

private int convertPxToDp(int px){
    return Math.round(px/(Resources.getSystem().getDisplayMetrics().xdpi/DisplayMetrics.DENSITY_DEFAULT));
}
1
Trinadh Koya

Si vous recherchez une calculatrice en ligne permettant de convertir des pixels DP, SP, en pouces, en millimètres, en points ou en pixels, à différentes densités d'écran, c'est l'outil le plus complet que je connaisse .

1
Paul Lammertsma

La réponse acceptée ci-dessus n’est pas tout à fait exacte. Selon les informations obtenues en inspectant Android code source:

Resources.getDimension() et getDimensionPixelOffset()/getDimensionPixelSize() ne diffèrent que par le fait que le premier retourne float tandis que les deux derniers renvoient la même valeur arrondie à int de manière appropriée. Pour tous, la valeur de retour est en pixels bruts.

Les trois fonctions sont implémentées en appelant Resources.getValue() et en convertissant ainsi obtenu TypedValue en appelant TypedValue.complexToDimension(), TypedValue.complexToDimensionPixelOffset() et TypedValue.complexToDimensionPixelSize(), respectivement.

Par conséquent, si vous souhaitez obtenir une valeur "brute" avec l'unité spécifiée dans la source XML, appelez Resources.getValue() et utilisez les méthodes de la classe TypedValue.

0
Jaromír Adamec

avec l'aide d'autres réponses, j'ai écrit cette fonction.

public static int convertToPixels(Context context, int nDP)
{
        final float conversionScale = context.getResources().getDisplayMetrics().density; 
        return (int) ((nDP * conversionScale) + 0.5f) ;
}
0
Abhishek

Voici une autre façon de le faire en utilisant des extensions kotlin:

val Int.dpToPx: Int
    get() = Math.round(this * Resources.getSystem().displayMetrics.density)

val Int.pxToDp: Int
    get() = Math.round(this / Resources.getSystem().displayMetrics.density)

et puis il peut être utilisé comme ça de partout

12.dpToPx

244.pxToDp
0
Quinn

DisplayMetrics displayMetrics = contaxt.getResources () .getDisplayMetrics ();

    int densityDpi = (int) (displayMetrics.density * 160f);
    int ratio = (densityDpi / DisplayMetrics.DENSITY_DEFAULT);
    int px;
    if (ratio == 0) {
        px = dp;
    } else {
        px = Math.round(dp * ratio);

    }
0
Sushil Mittal

N'hésitez pas à utiliser cette méthode, j'ai écrit:

int dpToPx(int dp)
{
    return (int) (dp * getResources().getDisplayMetrics().density + 0.5f);
}
0
Ben Kane

la variation sur la réponse ct_robs ci-dessus, si vous utilisez des entiers, cela évite non seulement la division par 0, mais produit également un résultat utilisable sur de petits périphériques:

dans les calculs de nombres entiers impliquant une division pour obtenir la plus grande précision, multipliez-vous d'abord avant la division pour réduire les effets de troncature.

px = dp * dpi/160 dp = px * 160/dpi

5 * 120 = 600/160 = 3

au lieu de

5 * (120/160 = 0) = 0

si vous voulez un résultat arrondi faites ceci

px = (10 * dp * dpi/160 + 5)/10 dp = (10 * px * 160/dpi + 5)/10

10 * 5 * 120 = 6000/160 = 37 + 5 = 42/10 = 4

0
user2624395