Conversione di pixel in dp


827

Ho creato la mia applicazione con l'altezza e la larghezza espresse in pixel per un dispositivo Pantech la cui risoluzione è 480x800.

Devo convertire l'altezza e la larghezza per un dispositivo G1.
Ho pensato che convertirlo in dp risolverà il problema e fornirà la stessa soluzione per entrambi i dispositivi.

Esiste un modo semplice per convertire i pixel in dp?
Eventuali suggerimenti?


1
Se stai cercando di fare una conversione una tantum (ad esempio per esportare gli sprite da Photoshop), ecco un elegante convertitore .
Paul Lammertsma,


Risposte:


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
Nota: quanto sopra sta convertendo i DIP in pixel. La domanda originale chiedeva come convertire i pixel in Dips!
Eurig Jones,

12
Ecco una vera risposta al PO: stackoverflow.com/questions/6656540/…
qix

119
È divertente come la risposta sia più utile quando in realtà non risponde alla domanda -_- Pensavo di volere ciò che la domanda poneva, poi mi sono reso conto di non averlo fatto! Quindi ottima risposta. Ho una domanda Come posso ottenere l'ultimo parametro per applyDimension? Posso semplicemente fare getResource().getDisplayMetrics()o c'è qualcos'altro?
Andy,

11
NOTA: operazione relativamente costosa. Prova a memorizzare nella cache i valori per un accesso più rapido
Entreco

8
Se non ha accesso Contextall'utilizzo dell'oggettoResources.getSystem().getDisplayMetrics()
Farshad Tahmasbi il

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
Potrebbe valere la pena restituire un int.Mathround (px) poiché la maggior parte dei metodi prevede un valore intero
Raj Labana

3
@MuhammadBabar Questo perché 160 dpi (mdpi) è la divinità di base da cui vengono calcolate le altre densità. hdpi, ad esempio, è considerato 1,5 volte la densità di mdpi, che è in realtà solo un altro modo di dire 240 dpi. Vedi la risposta di Zsolt Safrany di seguito per tutte le densità.
Stephen,

19
@TomTasche: dai documenti per Resource.getSystem()(l'enfasi mia): "Restituisce un oggetto Risorse condivise globali che fornisce l'accesso solo alle risorse di sistema (nessuna risorsa dell'applicazione) e non è configurato per la schermata corrente ( non può utilizzare le unità di dimensione , non cambia in base all'orientamento, ecc.) "
Vicky Chijwani,

2
Lo sviluppatore ha la possibilità di scegliere il valore / valore. È meglio dare il controllo allo sviluppatore.
Muhammad Nabeel Arif,

7
Consiglierei DisplayMetrics.DENSITY_DEFAULTinvece di 160f developer.android.com/reference/android/util/…
milcaepsilon,

285

Preferibilmente, inserire una 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;
}

5
Questo non funziona su tutti i dispositivi! Il risultato di questa risposta rispetto a quello dell'uso di TypedValue.applyDimension non è lo stesso su OnePlus 3T (probabilmente perché OnePlus ha il ridimensionamento personalizzato integrato nel sistema operativo). L'uso di TypedValue.applyDimension provoca un comportamento coerente tra i dispositivi.
Ben De La Haye,

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

density è uguale a

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

Usa questo convertitore online per giocare con i valori dpi.

EDIT: Sembra che non ci sia una relazione 1: 1 tra dpibucket e density. Sembra che l' Nexus 5Xessere xxhdpiabbia un densityvalore di 2.625(anziché 3). Guarda tu stesso nelle metriche del dispositivo .


3
"Sembra che il Nexus 5X essendo xxhdpi abbia un valore di densità di 2,6 (anziché 3)" - Tecnicamente il Nexus 5X è 420 dpi e il Nexus 6 / 6P è 560 dpi, né atterra direttamente in uno dei secchi standard, proprio come il Nexus 7 con tvdpi (213 dpi). Quindi il sito che elenca quelli come xxdpi e xxxhdpi è una farsa. Il tuo grafico È corretto e quei dispositivi si ridimensioneranno correttamente in base ai loro "speciali" bucket dpi.
Steven Byle,

108

Puoi usarlo .. senza contesto

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

Come accennato da @Stan .. l'utilizzo di questo approccio può causare problemi se il sistema cambia densità. Quindi state attenti!

Personalmente sto usando il contesto per farlo. È solo un altro approccio con cui volevo condividerti


11
Potresti non volerlo usare. Documentazione per getSystem () - "Restituisce un oggetto Risorse condivise globali che fornisce l'accesso solo alle risorse di sistema (nessuna risorsa dell'applicazione) e non è configurato per la schermata corrente (non può utilizzare le unità di dimensione, non cambia in base all'orientamento, ecc.) ".
Stan,

Secondo ciò che dice @Stan: questo è pericoloso e non dovresti usarlo, specialmente ora che i fattori di forma del dispositivo stanno diventando così complessi.
Saket,

93

Se puoi usare le dimensioni XML è molto semplice!

Nel tuo res/values/dimens.xml:

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

Quindi nel tuo Java:

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

Poiché px a dp dipende dalla densità dello schermo, non so come l'OP abbia ottenuto 120 in primo luogo, a meno che non abbia testato il metodo da px a dp su tutte le diverse dimensioni dello schermo.
Giovanni 61590,

75

Secondo la Guida allo sviluppo di Android:

px = dp * (dpi / 160)

Ma spesso ti consigliamo di farlo al contrario quando ricevi un disegno che è dichiarato in pixel. Così:

dp = px / (dpi / 160)

Se utilizzi un dispositivo da 240 dpi, questo rapporto è 1,5 (come indicato in precedenza), quindi significa che un'icona da 60px equivale a 40dp nell'applicazione.



7
160 è costante, risposta a letto
user25

2
@ user25 Ottima risposta in realtà. Non hai letto alcun documento sugli schermi Android? 160 è una costante comune in tutto il luogo quando si parla di densità dello schermo Android. Citazione da documenti: "schermi a media densità (mdpi) (~ 160 dpi). (Questa è la densità della linea di base)". Dai, amico
mykolaj,

70

Senza Context, eleganti metodi statici:

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 dice "Restituisce un oggetto Risorse condivise globali che fornisce l'accesso solo alle risorse di sistema (nessuna risorsa dell'applicazione) e non è configurato per la schermata corrente (non può utilizzare le unità di dimensione, non cambia in base all'orientamento, ecc.)" Questo praticamente dice che non dovresti farlo anche se in qualche modo funziona.
Austyn Mahoney,

Ho appena letto il commento di AustynMahoney e ho capito che questa risposta non è eccezionale come pensavo inizialmente, ma SO non mi lascerà annullare il mio voto ! Argh!
Vicky Chijwani,

45

Per DP to Pixel

Crea un valore in dimens.xml

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

Ottieni quel valore pixelcome:

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

39

È quindi possibile utilizzare il seguente formulatore per calcolare la giusta quantità di pixel da una dimensione specificata in 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);
}

4
Questo converte dp in pixel ma hai chiamato il tuo metodo convertToDp.
Qwertie,

4
+ 0.5f è spiegato qui -> developer.android.com/guide/practices/… . È usato per arrotondare al numero intero più vicino.
Bae

l'unica risposta giusta. potresti aggiungere la fonte developer.android.com/guide/practices/…
user25

web.archive.org/web/20140808234241/http://developer.android.com/… per un link che ha ancora il contenuto in questione
caw

39

Per chiunque usi Kotlin:

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

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

Uso:

64.toPx
32.toDp

Dai documenti per Resource.getSystem (): "Restituisce un oggetto Risorse condivise globali che fornisce l'accesso solo alle risorse di sistema (nessuna risorsa dell'applicazione) e non è configurato per la schermata corrente (non può utilizzare le unità di dimensione, non cambia in base a orientamento, ecc.) "
HendraWD,

@HendraWD I documenti possono essere fonte di confusione, le unità di dimensione che sta citando è il livello dell'applicazione che riduce le risorse. displayMetrics non è una risorsa a livello di applicazione. È una risorsa di sistema e restituisce i valori corretti. Questo codice funziona perfettamente su tutte le mie app Prod. Non ho mai avuto problemi.
Gunhan,


27

l'utilizzo di kotlin-extension lo rende migliore

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

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

AGGIORNARE:

Perché displayMetricsfa parte delle risorse condivise globali , possiamo usareResources.getSystem()

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

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

4
Perché dovresti aggiungerlo come estensione di Int, la responsabilità non deve fare nulla con il tipo Int.
htafoya,

19

Questo dovrebbe darti la conversione dp in pixel:

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

Questo dovrebbe darti i pixel di conversione in dp:

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

Giava

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

Probabilmente il modo migliore se hai la dimensione all'interno di valori / dimen è ottenere la dimensione direttamente dal metodo getDimension (), ti restituirà la dimensione già convertita in valore di pixel.

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

Giusto per spiegare meglio questo,

getDimension(int resourceId) 

restituirà la dimensione già convertita in pixel COME A FLOAT.

getDimensionPixelSize(int resourceId)

restituirà lo stesso ma troncato a int, quindi COME UN INTEGER.

Vedi riferimento Android


9
Per convertire dp in pixel.
public static int dp2px(Resources resource, int dp) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,   dp,resource.getDisplayMetrics());
}
Per convertire pixel in dp.
  public static float px2dp(Resources resource, float px)  {
    return (float) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, px,resource.getDisplayMetrics());
}

dove la risorsa è context.getResources ().


8
La risposta è sbagliata, perché non stai convertendo i pixel in dp - stai convertendo i pixel in pixel!
Yaroslav,

Px2dp è errato: restituirà lo stesso valore in pixel.
natario,

8

come questo:

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

dipende dal contesto, restituisce valore float, metodo statico

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


8

Approccio più elegante usando la funzione di estensione di 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()

Uso:

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

Adoro l'uso dell'estensione qui. Ho letto le funzioni come "converti in function name" che mi rendo conto che è al contrario in questo caso. Per chiarire l'intento di ciascuna funzione, i nomi delle funzioni potrebbero essere aggiornati per leggere rispettivamente dpToPx e pxToDp.
Maxwell,

Dai documenti per Resource.getSystem (): "Restituisce un oggetto Risorse condivise globali che fornisce l'accesso solo alle risorse di sistema (nessuna risorsa dell'applicazione) e non è configurato per la schermata corrente (non può utilizzare le unità di dimensione, non cambia in base a orientamento, ecc.) "
HendraWD,

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

2
Non è solo lo stesso di quello che è coperto in molte delle altre risposte a questa domanda?
TZHX,

7

Nel caso in cui si sviluppi un'applicazione critica per le prestazioni, considerare la seguente classe ottimizzata:

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

Ha senso solo se si eseguono conversioni molto frequentemente. Nel mio caso lo faccio.
Pavel,

Che cos'è 160f? Perché lo usi, perché è 160?
Dephinera,

160 => 160 dpi e questo è per convertire le misure a causa della formula
xAqweRx

6

per convertire i pixel in dp usa TypedValue .

Come menzionato nella documentazione: Contenitore per un valore di dati tipizzato dinamicamente.

e usa il metodo applyDimension :

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

che converte un valore di dati complessi non compressi che contiene una dimensione al suo valore in virgola mobile finale come il seguente:

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

Spero che aiuti .


6

Funziona così per me:

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

Puoi fare lo stesso per la larghezza.



4

Dovresti usare dp come faresti con i pixel. Questo è tutto ciò che sono; visualizzare pixel indipendenti. Usa gli stessi numeri che avresti su uno schermo a media densità e le dimensioni saranno magicamente corrette su uno schermo ad alta densità.

Tuttavia, sembra che ciò di cui hai bisogno sia l'opzione fill_parent nella progettazione del layout. Utilizzare fill_parent quando si desidera che la vista o il controllo si espanda a tutte le dimensioni rimanenti nel contenitore padre.


in realtà il mio problema è che la mia applicazione è codificata per uno schermo ad alta densità e ora deve essere convertita in uno schermo a bassa densità ..
Indhu

modificare i pixel per uno schermo a media densità (è possibile impostare uno schermo a media densità nell'emulatore) e sostituire il pixel con dp. Tuttavia, è possibile creare applicazioni più flessibili utilizzando fill_parent e layout multipli.
Michael Lowman,

Infine, non avevo altra scelta che cambiare manualmente tutti i px in dp .. :(
Indhu,

1
Almeno la prossima volta userai prima dp e non dovrai cambiare nulla :) Anche se dovrebbe essere possibile usare layout che non richiedono un posizionamento assoluto per la maggior parte delle cose.
Michael Lowman,

Dato che era la mia prima app ... ho fatto questo errore ... non lo farò mai più ... :)
Indhu,

4

PXe DPsono diversi ma simili.

DPè la risoluzione quando si calcola solo la dimensione fisica dello schermo. Quando lo usi DPridimensiona il layout su schermi di dimensioni simili con dimensioni diversepixel densità .

Occasionalmente pixels, tuttavia, in realtà lo desideri , e quando hai a che fare con dimensioni in codice hai sempre a che fare con reale pixels, a meno che non le converti.

Quindi su un dispositivo Android, hdpischermo di dimensioni normali , 800x480 is 533x320in DP(credo). Per convertire DPin pixels /1.5, per riconvertire *1.5. Questo è solo per la dimensione di uno schermo e dpi, cambierebbe a seconda del design. I nostri artisti mi danno pixelsperò e mi converto DPcon l' 1.5equazione sopra .


3

Se vuoi valori interi , allora usando Math.round () arrotonderai il float all'intero più vicino.

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

3

La migliore risposta arriva dal framework Android stesso: basta usare questa uguaglianza ...

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

(converte dp in px)


2

Questo lavoro per me (C #):

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

Non è una risposta a questa domanda ma per C # funziona. Grazie
Yekmer Simsek il

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
}

Giava

   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;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.