Pixel in dp konvertieren


827

Ich habe meine Anwendung mit der in Pixel angegebenen Höhe und Breite für ein Pantech-Gerät mit einer Auflösung erstellt 480x800.

Ich muss Höhe und Breite für ein G1-Gerät konvertieren.
Ich dachte, die Konvertierung in dp würde das Problem lösen und für beide Geräte die gleiche Lösung bieten.

Gibt es eine einfache Möglichkeit, Pixel in dp umzuwandeln?
Irgendwelche Vorschläge?


1
Wenn Sie eine einmalige Konvertierung durchführen möchten (z. B. zum Exportieren von Sprites aus Photoshop), finden Sie hier einen praktischen Konverter .
Paul Lammertsma


Antworten:


1037
// Converts 14 dip into its equivalent px
float dip = 14f;
Resources r = getResources();
float px = TypedValue.applyDimension(
    TypedValue.COMPLEX_UNIT_DIP,
    dip,
    r.getDisplayMetrics()
);

332
Hinweis: Oben werden DIPs in Pixel konvertiert. In der ursprünglichen Frage wurde gefragt, wie Pixel in Dips konvertiert werden können.
Eurig Jones

12
Hier ist eine echte Antwort auf das OP: stackoverflow.com/questions/6656540/…
qix

119
Es ist lustig, wie hilfreich die Antwort ist, wenn sie die Frage nicht wirklich beantwortet. -_- Ich dachte, ich wollte, was die Frage stellte, dann wurde mir klar, dass ich es nicht tat! So tolle Antwort. Ich habe eine Frage. Wie kann ich den letzten Parameter für erhalten applyDimension? Kann ich es einfach tun getResource().getDisplayMetrics()oder gibt es noch etwas anderes?
Andy

11
HINWEIS: relativ teurer Betrieb. Versuchen Sie, die Werte für einen schnelleren
Zugriff zwischenzuspeichern

8
Wenn Sie keinen Zugriff auf die ContextObjektnutzung habenResources.getSystem().getDisplayMetrics()
Farshad Tahmasbi

871
/**
 * 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);
}

8
Es könnte sich lohnen, einen int Math.round (px) zurückzugeben, da die meisten Methoden einen ganzzahligen Wert erwarten
Raj Labana

3
@MuhammadBabar Dies liegt daran, dass 160 dpi (mdpi) die Basislinie ist, aus der andere Dichten berechnet werden. hdpi zum Beispiel wird als 1,5-fache Dichte von mdpi angesehen, was eigentlich nur eine andere Art ist, 240 dpi zu sagen. Siehe Zsolt Safranys Antwort unten für alle Dichten.
Stephen

19
@TomTasche: Aus den Dokumenten für Resource.getSystem()(Hervorhebung von mir): " Gibt ein globales freigegebenes Ressourcenobjekt zurück, das nur Zugriff auf Systemressourcen (keine Anwendungsressourcen) bietet und nicht für den aktuellen Bildschirm konfiguriert ist ( kann keine Dimensionseinheiten verwenden , ändert sich nicht) basierend auf Orientierung usw.). "
Vicky Chijwani

2
Entwickler haben die Wahl, den Wert zu decken. Es ist besser, dem Entwickler die Kontrolle zu geben.
Muhammad Nabeel Arif

7
Ich würde DisplayMetrics.DENSITY_DEFAULTanstelle von 160f developer.android.com/reference/android/util/…
milcaepsilon

285

Am besten in eine Util.java-Klasse einfügen

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;
}

5
Dies funktioniert nicht auf allen Geräten! Das Ergebnis dieser Antwort im Vergleich zur Verwendung von TypedValue.applyDimension ist auf einem OnePlus 3T nicht dasselbe (wahrscheinlich, weil in OnePlus eine benutzerdefinierte Skalierung im Betriebssystem integriert ist). Die Verwendung von TypedValue.applyDimension führt zu einem konsistenten Verhalten auf allen Geräten.
Ben De La Haye

197
float density = context.getResources().getDisplayMetrics().density;
float px = someDpValue * density;
float dp = somePxValue / density;

density gleich

  • .75ein ldpi( 120dpi)
  • 1.0ein mdpi( 160dpi; Grundlinie)
  • 1.5ein hdpi( 240dpi)
  • 2.0ein xhdpi( 320dpi)
  • 3.0ein xxhdpi( 480dpi)
  • 4.0ein xxxhdpi( 640dpi)

Verwenden Sie diesen Online-Konverter , um mit dpi-Werten herumzuspielen.

EDIT: Es scheint, dass es keine 1: 1-Beziehung zwischen dpiBucket und gibt density. Es sieht so aus, als hätte das Nexus 5XWesen xxhdpieinen densityWert von 2.625(anstelle von 3). Überzeugen Sie sich selbst in den Gerätemetriken .


3
"Es sieht so aus, als ob das Nexus 5X xxhdpi einen Dichtewert von 2,6 (anstelle von 3) hat." - Technisch gesehen ist das Nexus 5X 420 dpi und das Nexus 6 / 6P ist 560 dpi Nexus 7 mit tvdpi (213dpi). Die Seite, auf der diese als xxdpi und xxxhdpi aufgeführt sind, ist also eine Farce. Ihr Diagramm ist korrekt, und diese Geräte skalieren anhand eines ihrer "speziellen" dpi-Buckets ordnungsgemäß.
Steven Byle

108

Sie können dies .. ohne Kontext verwenden

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

Wie bei @Stan erwähnt, kann die Verwendung dieses Ansatzes zu Problemen führen, wenn das System die Dichte ändert. Also sei dir dessen bewusst!

Persönlich benutze ich Context, um das zu tun. Es ist nur ein weiterer Ansatz, mit dem ich Sie teilen wollte


11
Möglicherweise möchten Sie dies nicht verwenden. Dokumentation für getSystem () - "Gibt ein globales freigegebenes Ressourcenobjekt zurück, das nur Zugriff auf Systemressourcen (keine Anwendungsressourcen) bietet und nicht für den aktuellen Bildschirm konfiguriert ist (kann keine Dimensionseinheiten verwenden, ändert sich nicht basierend auf der Ausrichtung usw.) . "
Stan

Zweitens, was @Stan sagt: Dies ist gefährlich und sollte nicht verwendet werden, insbesondere jetzt, wo Geräteformfaktoren so komplex werden.
Saket

93

Wenn Sie die Dimensionen XML verwenden können, ist es sehr einfach!

In Ihrem res/values/dimens.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="thumbnail_height">120dp</dimen>
    ...
    ...
</resources>

Dann in Ihrem Java:

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

Da px to dp von der Bildschirmdichte abhängt, weiß ich nicht, wie der OP überhaupt 120 wurde, es sei denn, er oder sie hat die px to dp-Methode auf allen verschiedenen Bildschirmgrößen getestet.
John61590

75

Laut dem Android Development Guide:

px = dp * (dpi / 160)

Aber oft möchten Sie dies umgekehrt tun, wenn Sie ein Design erhalten, das in Pixel angegeben ist. Damit:

dp = px / (dpi / 160)

Wenn Sie ein 240-dpi-Gerät verwenden, beträgt dieses Verhältnis 1,5 (wie zuvor angegeben). Dies bedeutet, dass ein 60-Pixel-Symbol in der Anwendung 40 dp entspricht.



7
160 ist konstant, Bett Antwort
Benutzer25

2
@ user25 Tatsächlich eine großartige Antwort. Hast du keine Dokumente auf Android-Bildschirmen gelesen? 160 ist eine weit verbreitete Konstante, wenn es um Android-Bildschirmdichten geht. Zitat aus der Dokumentation: "Bildschirme mittlerer Dichte (mdpi) (~ 160 dpi). (Dies ist die Basisliniendichte)". Komm schon, Mann
Mykolaj

70

Ohne Contextelegante statische Methoden:

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

24
Resources.getSystem()javadoc sagt: "Gibt ein globales freigegebenes Ressourcenobjekt zurück, das nur Zugriff auf Systemressourcen (keine Anwendungsressourcen) bietet und nicht für den aktuellen Bildschirm konfiguriert ist (kann keine Dimensionseinheiten verwenden, ändert sich nicht basierend auf der Ausrichtung usw.)." Dies sagt ziemlich genau, dass Sie dies nicht tun sollten, auch wenn es irgendwie funktioniert.
Austyn Mahoney

Ich habe gerade den Kommentar von @ AustynMahoney gelesen und festgestellt, dass diese Antwort nicht so gut ist, wie ich ursprünglich dachte, aber SO kann ich meine Gegenstimme nicht rückgängig machen ! Argh!
Vicky Chijwani

45

Zum DP to Pixel

Erstellen Sie einen Wert in dimens.xml

<dimen name="textSize">20dp</dimen>

Erhalten Sie diesen Wert pixelals:

int sizeInPixel = context.getResources().getDimensionPixelSize(R.dimen.textSize);

39

Sie können daher den folgenden Formulierer verwenden, um die richtige Anzahl von Pixeln aus einer in dp angegebenen Dimension zu berechnen

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

4
Dies konvertiert dp in Pixel, aber Sie haben Ihre Methode aufgerufen convertToDp.
Qwertie

4
+ 0.5f wird hier erklärt -> developer.android.com/guide/practices/… . Es wird verwendet, um auf die nächste ganze Zahl aufzurunden.
Bae

die einzig richtige Antwort. Sie können die Quelle developer.android.com/guide/practices/…
user25

web.archive.org/web/20140808234241/http://developer.android.com/… für einen Link, der noch den fraglichen Inhalt hat
caw

39

Für alle, die Kotlin verwenden:

val Int.toPx: Int
    get() = (this * Resources.getSystem().displayMetrics.density).toInt()

val Int.toDp: Int
    get() = (this / Resources.getSystem().displayMetrics.density).toInt()

Verwendungszweck:

64.toPx
32.toDp

Aus den Dokumenten für Resource.getSystem (): "Gibt ein globales freigegebenes Ressourcenobjekt zurück, das nur Zugriff auf Systemressourcen (keine Anwendungsressourcen) bietet und nicht für den aktuellen Bildschirm konfiguriert ist (kann keine Dimensionseinheiten verwenden, ändert sich nicht basierend auf Orientierung usw.). "
HendraWD

@HendraWD Die Dokumente sind möglicherweise verwirrend. Die erwähnten Dimensionseinheiten sind die Dimensionsressourcen auf Anwendungsebene. displayMetrics ist keine Ressource auf Anwendungsebene. Es ist eine Systemressource und gibt die richtigen Werte zurück. Dieser Code funktioniert auf allen meinen Prod-Apps einwandfrei. Hatte nie ein Problem.
Gunhan


27

Die Verwendung der Kotlin-Erweiterung macht es besser

fun Int.toPx(context: Context): Int = (this * context.resources.displayMetrics.density).toInt()

fun Int.toDp(context: Context): Int = (this / context.resources.displayMetrics.density).toInt()

AKTUALISIEREN:

Da dies displayMetricsTeil global geteilter Ressourcen ist , können wir es verwendenResources.getSystem()

fun Int.toPx(): Int = (this * Resources.getSystem().displayMetrics.density).toInt()

fun Int.toDp(): Int = (this / Resources.getSystem().displayMetrics.density).toInt()

4
Warum sollten Sie es als Erweiterung von Int hinzufügen, die Verantwortung muss nichts mit dem Int-Typ zu tun haben.
Htafoya

19

Dies sollte Ihnen die Konvertierung von dp in Pixel geben:

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

Dies sollte Ihnen die Konvertierungspixel in dp geben:

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

19

Kotlin

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)
}

Java

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

12

Wenn Sie die Bemaßung innerhalb von Werten / Bemaßung haben, ist es wahrscheinlich der beste Weg, die Bemaßung direkt von der Methode getDimension () abzurufen. Sie gibt die Bemaßung zurück, die bereits in einen Pixelwert konvertiert wurde.

context.getResources().getDimension(R.dimen.my_dimension)

Nur um das besser zu erklären,

getDimension(int resourceId) 

gibt die Dimension zurück, die bereits in Pixel AS A FLOAT konvertiert wurde.

getDimensionPixelSize(int resourceId)

wird das gleiche zurückgeben, aber auf int abgeschnitten, also ALS INTEGER.

Siehe Android-Referenz


9
Um dp in Pixel umzuwandeln.
public static int dp2px(Resources resource, int dp) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,   dp,resource.getDisplayMetrics());
}
Pixel in dp konvertieren.
  public static float px2dp(Resources resource, float px)  {
    return (float) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, px,resource.getDisplayMetrics());
}

Dabei ist die Ressource context.getResources ().


8
Die Antwort ist falsch, weil Sie keine Pixel in dp konvertieren - Sie konvertieren Pixel in Pixel!
Jaroslaw

Das px2dp ist falsch - gibt den gleichen Wert in Pixel zurück.
Natario

8

so was:

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;
    }
}

abhängig vom Kontext, return float value, statische Methode

von: https://github.com/Trinea/android-common/blob/master/src/cn/trinea/android/common/util/ScreenUtils.java#L15


8

Eleganterer Ansatz mit der Erweiterungsfunktion von 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()

Verwendungszweck:

println("16 dp in pixel: ${16.dpToPx}")
println("16 px in dp: ${16.pxToDp}")

Ich liebe die Verwendung der Erweiterung hier. Ich habe die Funktionen als "konvertieren in function name" gelesen, was in diesem Fall rückwärts ist. Um die Absicht jeder Funktion zu verdeutlichen, könnten die Namen der Funktionen aktualisiert werden, um dpToPx bzw. pxToDp zu lesen.
Maxwell

Aus den Dokumenten für Resource.getSystem (): "Gibt ein globales freigegebenes Ressourcenobjekt zurück, das nur Zugriff auf Systemressourcen (keine Anwendungsressourcen) bietet und nicht für den aktuellen Bildschirm konfiguriert ist (kann keine Dimensionseinheiten verwenden, ändert sich nicht basierend auf Orientierung usw.). "
HendraWD

7
float scaleValue = getContext().getResources().getDisplayMetrics().density;
int pixels = (int) (dps * scaleValue + 0.5f);

2
Ist dies nicht dasselbe wie in vielen anderen Antworten auf diese Frage?
TZHX

7

Wenn Sie eine leistungskritische Anwendung entwickeln, berücksichtigen Sie bitte die folgende optimierte Klasse:

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;
    }
}

Es macht nur Sinn, wenn Sie wirklich häufig Konvertierungen durchführen. In meinem Fall tue ich.
Pavel

Was ist 160f? Warum benutzt du es, warum ist es 160?
Dephinera

160 => 160dpi und dies ist für die Konvertierung von Maßnahmen aufgrund der Formel
xAqweRx

6

Um Pixel in dp zu konvertieren, verwenden Sie den TypedValue .

Wie in der Dokumentation erwähnt: Container für einen dynamisch typisierten Datenwert.

und verwenden Sie die Methode applyDimension :

public static float applyDimension (int unit, float value, DisplayMetrics metrics) 

Hiermit wird ein entpackter komplexer Datenwert, der eine Dimension enthält, wie folgt in seinen endgültigen Gleitkommawert konvertiert:

Resources resource = getResources();
float dp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, 69, resource.getDisplayMetrics());

Ich hoffe, das hilft .


6

So funktioniert es bei mir:

DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int  h = displaymetrics.heightPixels;
float  d = displaymetrics.density;
int heightInPixels=(int) (h/d);

Sie können dasselbe für die Breite tun.



4

Sie sollten dp genauso verwenden wie Pixel. Das ist alles was sie sind; unabhängige Pixel anzeigen. Verwenden Sie die gleichen Zahlen wie auf einem Bildschirm mittlerer Dichte, und die Größe ist auf einem Bildschirm hoher Dichte magisch korrekt.

Es hört sich jedoch so an, als ob Sie die Option fill_parent in Ihrem Layoutdesign benötigen. Verwenden Sie fill_parent, wenn Ihre Ansicht oder Ihr Steuerelement auf die gesamte verbleibende Größe im übergeordneten Container erweitert werden soll.


Eigentlich ist mein Problem, dass meine Anwendung für Bildschirme mit hoher Dichte codiert ist und jetzt in Bildschirme mit niedriger Dichte konvertiert werden muss.
Indhu

Ändern Sie Ihre Pixel für einen Bildschirm mittlerer Dichte (Sie können im Emulator einen Bildschirm mittlerer Dichte einrichten) und ersetzen Sie das Pixel durch dp. Flexiblere Anwendungen können jedoch mit fill_parent und mehreren Layouts erstellt werden.
Michael Lowman

Schließlich hatte ich keine andere Wahl, als alle px manuell in dp zu ändern .. :(
Indhu

1
Zumindest beim nächsten Mal werden Sie zuerst dp verwenden und müssen nichts ändern :) Obwohl es möglich sein sollte, Layouts zu verwenden, die für die meisten Dinge keine absolute Positionierung erfordern.
Michael Lowman

Da es meine erste App war ... habe ich diesen Fehler gemacht ... ich werde es nie wieder tun ... :)
Indhu

4

PXund DPsind unterschiedlich, aber ähnlich.

DPist die Auflösung, wenn Sie nur die physische Größe des Bildschirms berücksichtigen. Wenn Sie es verwenden DP, wird Ihr Layout auf andere Bildschirme ähnlicher Größe mit unterschiedlicher pixelDichte skaliert .

Gelegentlich möchten Sie jedoch tatsächlich pixels, und wenn Sie sich mit Dimensionen im Code befassen, haben Sie es immer mit real zu tun pixels, es sei denn, Sie konvertieren sie.

Also auf einem Android-Gerät, normal großer hdpiBildschirm, 800x480 is 533x320in DP(glaube ich). Zur Umwandlung DPin pixels /1.5, zu konvertieren zurück *1.5. Dies gilt nur für die eine Bildschirmgröße und dpiwürde sich je nach Design ändern. Unsere Künstler geben mirpixels aber und ich konvertiere DPmit der obigen 1.5Gleichung.


3

Wenn Sie Integer- Werte möchten, wird der Float mit Math.round () auf die nächste Ganzzahl gerundet.

public static int pxFromDp(final float dp) {
        return Math.round(dp * Resources.getSystem().getDisplayMetrics().density);
    }

3

Die beste Antwort kommt vom Android-Framework selbst: Verwenden Sie einfach diese Gleichheit ...

public static int dpToPixels(final DisplayMetrics display_metrics, final float dps) {
    final float scale = display_metrics.density;
    return (int) (dps * scale + 0.5f);
}

(konvertiert dp in px)


2

Das funktioniert für mich (C #):

int pixels = (int)((dp) * Resources.System.DisplayMetrics.Density + 0.5f);

Keine Antwort auf diese Frage, aber für C # funktioniert es. Vielen Dank
Yekmer Simsek

2

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;
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.