Convertendo pixels em dp


827

Eu criei meu aplicativo com a altura e largura fornecidas em pixels para um dispositivo Pantech cuja resolução é 480x800.

Preciso converter altura e largura para um dispositivo G1.
Eu pensei que convertê-lo em dp resolverá o problema e fornecerá a mesma solução para os dois dispositivos.

Existe alguma maneira fácil de converter pixels em dp?
Alguma sugestão?


1
Se você deseja fazer uma conversão única (por exemplo, para exportar sprites do Photoshop), aqui está um conversor bacana .
— Paul Lammertsma


Respostas:


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: O acima está convertendo DIPs em pixels. A pergunta original perguntou como converter pixels em Dips!
— Eurig Jones 13/03/12

12
Aqui está uma resposta real para o OP: stackoverflow.com/questions/6656540/...
— qix

119
É engraçado como a resposta é mais útil quando realmente não responde à pergunta -_- Eu pensei que queria o que a pergunta fazia, então percebi que não! Ótima resposta. Eu tenho uma pergunta. Como posso obter o último parâmetro para applyDimension? Posso fazer getResource().getDisplayMetrics()ou há algo mais?
— Andy

11
NOTA: operação relativamente cara. Tente armazenar em cache os valores para um acesso mais rápido
— Entreco

8
Se não têm acesso ao Contextuso de objetoResources.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
Pode valer a pena retornar um int Math.round (px) como a maioria dos métodos de esperar um valor inteiro
— Raj Labana

3
@MuhammadBabar Isso ocorre porque 160 dpi (mdpi) é a unidade base da qual outras densidades são calculadas. O hdpi, por exemplo, é considerado 1,5x a densidade do mdpi, que é realmente apenas outra maneira de dizer 240 dpi. Veja a resposta da Zsolt Safrany abaixo para todas as densidades.
— Stephen

19
@TomTasche: Dos documentos para Resource.getSystem()(ênfase minha): "Retorne um objeto Global compartilhado de Recursos que fornece acesso apenas aos recursos do sistema (sem recursos de aplicativos) e não está configurado para a tela atual ( não pode usar unidades de dimensão , não muda com base na orientação, etc) ".
— Vicky Chijwani

2
O desenvolvedor tem a opção de limitar / limitar o valor. É melhor dar controle ao desenvolvedor.
— Muhammad Nabeel Arif

7
Eu recomendo DisplayMetrics.DENSITY_DEFAULTem vez de 160f developer.android.com/reference/android/util/...
— milcaepsilon

285

Coloque preferencialmente em uma 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
Isso não funciona em todos os dispositivos! O resultado desta resposta em relação ao uso de TypedValue.applyDimension não é o mesmo no OnePlus 3T (provavelmente porque o OnePlus possui dimensionamento personalizado incorporado ao sistema operacional). O uso de TypedValue.applyDimension causa um comportamento consistente entre os dispositivos.
— Ben De La Haye

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

density é igual a

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

Use este conversor online para brincar com os valores de dpi.

EDIT: Parece que não há relação 1: 1 entre dpibucket e density. Parece que o Nexus 5Xser xxhdpitem um densityvalor de 2.625(em vez de 3). Veja você mesmo nas Métricas do dispositivo .


3
"Parece que o Nexus 5X sendo xxhdpi tem um valor de densidade de 2,6 (em vez de 3)" - Tecnicamente, o Nexus 5X tem 420dpi e o Nexus 6 / 6P é 560dpi, nem pousa diretamente em um dos baldes padrão, assim como o Nexus 7 com tvdpi (213 dpi). Portanto, o site que lista aqueles como xxdpi e xxxhdpi é uma farsa. Seu gráfico está correto e esses dispositivos serão dimensionados adequadamente com base em seus baldes de dpi "especiais".
— Steven Byle

108

Você pode usar isso .. sem contexto

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

Como o @Stan mencionou .. usar essa abordagem pode causar problemas se o sistema alterar a densidade. Então, fique ciente disso!

Pessoalmente, estou usando o Contexto para fazer isso. É apenas outra abordagem com a qual eu queria compartilhar você


11
Você pode não querer usar isso. Documentação para getSystem () - "Retorna um objeto Global compartilhado de Recursos que fornece acesso apenas aos recursos do sistema (sem recursos do aplicativo) e não está configurado para a tela atual (não pode usar unidades de dimensão, não muda com base na orientação, etc.) . "
— Stan

Afastando o que @Stan está dizendo: isso é perigoso e você não deve usá-lo, especialmente agora quando os fatores de forma do dispositivo estão se tornando tão complexos.
— Saket

93

Se você pode usar o XML das dimensões, é muito simples!

No seu res/values/dimens.xml:

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

Então no seu Java:

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

Como px para dp depende da densidade da tela, não sei como o OP obteve 120 em primeiro lugar, a menos que ele tenha testado o método px para dp em todos os tamanhos de tela diferentes.
— precisa saber é o seguinte

75

De acordo com o Guia de desenvolvimento do Android:

px = dp * (dpi / 160)

Mas, muitas vezes, você deseja fazer isso de maneira inversa ao receber um design declarado em pixels. Assim:

dp = px / (dpi / 160)

Se você estiver em um dispositivo de 240 dpi, essa proporção é de 1,5 (como mencionado anteriormente), então isso significa que um ícone de 60px é igual a 40dp no aplicativo.



7
160 é constante, a resposta cama
— USER25

2
@ user25 Ótima resposta, na verdade. Você não leu nenhum documento nas telas do Android? 160 é uma constante comum em todo o lugar quando se fala em densidades de tela do Android. Citação de documentos: "telas de densidade média (mdpi) (~ 160dpi). (Essa é a densidade da linha de base)". Vamos lá, cara
— mykolaj

70

Sem Contextmétodos estáticos elegantes:

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 diz "Retorne um objeto Global compartilhado de Recursos que fornece acesso apenas aos recursos do sistema (sem recursos do aplicativo) e não está configurado para a tela atual (não pode usar unidades de dimensão, não muda com base na orientação, etc.)." Isso praticamente diz que você não deveria fazer isso, mesmo que de alguma forma funcione.
— Austyn Mahoney

Acabei de ler o comentário do @ AustynMahoney e percebi que essa resposta não é tão boa quanto eu pensava, mas SO não vai me deixar desfazer o meu voto ! Argh!
— Vicky Chijwani

45

Para DP to Pixel

Crie um valor em dimens.xml

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

Obtenha esse valor pixelcomo:

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

39

Portanto, você pode usar o formulador a seguir para calcular a quantidade correta de pixels de uma dimensão especificada em 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
Isso converte dp em pixels, mas você chamou seu método convertToDp.
— Qwertie

4
+ 0.5f é explicado aqui -> developer.android.com/guide/practices/… . É usado para arredondar para o número inteiro mais próximo.
— Bae

a única resposta certa. você pode adicionar o código-fonte developer.android.com/guide/practices/…
— user25 28/08

web.archive.org/web/20140808234241/http://developer.android.com/… para um link que ainda tem o conteúdo em questão
— caw

39

Para quem usa o 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

Nos documentos de Resource.getSystem (): "Retorne um objeto Global compartilhado de Recursos que fornece acesso apenas aos recursos do sistema (sem recursos do aplicativo) e não está configurado para a tela atual (não pode usar unidades de dimensão, não muda com base em orientação etc.) ".
— precisa saber é o seguinte

@HendraWD Os documentos podem ser confusos, as unidades de dimensão mencionadas são o nível de seu aplicativo que diminui os recursos. displayMetrics não é um recurso no nível do aplicativo. É um recurso do sistema e retorna os valores corretos. Este código está funcionando bem em todos os meus aplicativos Prod. Nunca tive um problema.
— Gunhan


27

usando o kotlin-extension torna melhor

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

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

ATUALIZAR:

Como displayMetricsfaz parte dos Recursos compartilhados globais , podemos usarResources.getSystem()

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

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

4
Por que você o adicionaria como uma extensão do Int, a responsabilidade não precisa fazer nada com o tipo Int.
— Htafoya 30/10/19

19

Isso deve fornecer a conversão dp para pixels:

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

Isso deve fornecer os pixels de conversão para 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)
}

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

Provavelmente, a melhor maneira de obter a dimensão dentro de values ​​/ dimen é obtendo a dimensão diretamente do método getDimension (), ela retornará a dimensão já convertida em valor de pixel.

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

Apenas para explicar melhor isso,

getDimension(int resourceId) 

retornará a dimensão já convertida em pixel AS A FLOAT.

getDimensionPixelSize(int resourceId)

retornará o mesmo, mas truncado para int, portanto AS INTEGER.

Consulte referência Android


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

onde o recurso é context.getResources ().


8
A resposta está errada, porque você não está convertendo pixels em dp - você está convertendo pixels em pixels!
— Yaroslav

O px2dp está errado - retornará o mesmo valor em pixels.
— Natario #

8

como isso:

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

dependente do contexto, retornar valor flutuante, método estático

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


8

Abordagem mais elegante usando a função de extensão do 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 o uso da extensão aqui. Eu li as funções como "converter para function name", que eu percebo que estão ao contrário neste caso. Para esclarecer a intenção de cada função, os nomes das funções podem ser atualizados para ler dpToPx e pxToDp, respectivamente.
— Maxwell

Nos documentos de Resource.getSystem (): "Retorne um objeto Global compartilhado de Recursos que fornece acesso apenas aos recursos do sistema (sem recursos do aplicativo) e não está configurado para a tela atual (não pode usar unidades de dimensão, não muda com base em orientação etc.) ".
— precisa saber é o seguinte

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

2
Não é o mesmo que está coberto em muitas das outras respostas a esta pergunta?
— TZHX

7

Caso esteja desenvolvendo um aplicativo crítico de desempenho, considere a seguinte classe otimizada:

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

Só faz sentido se você fizer conversões com muita frequência. No meu caso eu faço.
— Pavel

O que é 160f? Por que você usa, por que é 160?
— dephinera

160 => 160dpi e isto é para medidas de conversão, porque de fórmula
— xAqweRx

6

para converter pixels em dp, use o TypedValue .

Conforme a documentação mencionada: Contêiner para um valor de dados digitado dinamicamente.

e use o método applyDimension :

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

que Converte um valor de dados complexos descompactado, mantendo uma dimensão em seu valor final de ponto flutuante, como o seguinte:

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

Espero que ajude .


6

É assim que funciona para mim:

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

Você pode fazer o mesmo para a largura.



4

Você deve usar o dp como faria com os pixels. Isso é tudo o que são; exibir pixels independentes. Use os mesmos números que você usaria em uma tela de densidade média e o tamanho estará magicamente correto em uma tela de alta densidade.

No entanto, parece que você precisa da opção fill_parent no seu design de layout. Use fill_parent quando desejar que sua visualização ou controle se expanda para todo o tamanho restante no contêiner pai.


na verdade, o meu problema é o meu pedido é codificado para a tela de alta densidade e agora ele precisa ser convertido para a tela de baixa densidade ..
— Indhu

modifique seus pixels para uma tela de densidade média (você pode configurar uma tela de densidade média no emulador) e substitua o pixel por dp. No entanto, aplicativos mais flexíveis podem ser feitos usando fill_parent e vários layouts.
— Michael Lowman

Finalmente, eu não tinha opção a não ser alterar manualmente todos os px para dp .. :(
— Indhu

1
Pelo menos da próxima vez, você usará o dp primeiro e não precisará alterar nada :) Embora seja possível usar layouts que não exijam posicionamento absoluto para a maioria das coisas.
— Michael Lowman

Desde que foi o meu primeiro aplicativo .. eu cometi esse erro ... eu nunca vou fazê-lo novamente ... :) #
— 314 Indhu

4

PXe DPsão diferentes, mas semelhantes.

DPé a resolução quando você considera apenas o tamanho físico da tela. Ao usá- DPlo, o layout será dimensionado para outras telas de tamanhos semelhantes com pixeldensidades diferentes .

Ocasionalmente, você realmente deseja pixels, e quando lida com dimensões no código, está sempre lidando com real pixels, a menos que as converta.

Então, em um dispositivo Android, hdpitela de tamanho normal , 800x480 is 533x320em DP(eu acredito). Para converter DPem pixels /1.5, para converter de volta *1.5. Isso é apenas para o tamanho de uma tela e dpiisso mudaria dependendo do design. pixelsPorém, nossos artistas me deram e eu me converti DPcom a 1.5equação acima .


3

Se você deseja valores inteiros , usar Math.round () arredondará o valor flutuante para o número inteiro mais próximo.

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

3

A melhor resposta vem da própria estrutura do Android: basta usar essa igualdade ...

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 em px)


2

Isso funciona para mim (C #):

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

Não é uma resposta para esta pergunta, mas para o C # funciona. Obrigado
— 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;
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.