Преобразование пикселей в dp

Я создал свое приложение с высотой и шириной, заданной в пикселях для устройства Pantech с разрешением 480x800.

Мне нужно преобразовать высоту и ширину для устройства G1. Я думал, что преобразование его в dp решит проблему и обеспечит такое же решение для обоих устройств.

Есть ли простой способ конвертировать пиксели в dp? Любые предложения?

Ответ 1

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

Ответ 2

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

Ответ 3

Желательно добавить класс 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;
}

Ответ 4

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

density равно

  • .75 on ldpi (120 dpi)
  • 1.0 on mdpi (160 dpi, базовая линия)
  • 1.5 on hdpi (240 dpi)
  • 2.0 on xhdpi (320 dpi)
  • 3.0 on xxhdpi (480 dpi)
  • 4.0 on xxxhdpi (640 dpi)

Используйте этот онлайн-конвертер, чтобы играть со значениями dpi.

EDIT: Кажется, нет отношения 1:1 между ведром dpi и density. Похоже, что Nexus 5X имеет xxhdpi имеет значение density 2.625 (вместо 3). Посмотрите сами в Показатели устройства.

Ответ 5

Если вы можете использовать размеры XML, это очень просто!

В res/values/dimens.xml:

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

Затем в вашей Java:

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

Ответ 6

Вы можете использовать это.. без контекста

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

Как упомянул @Stan.. использование этого подхода может вызвать проблемы, если система изменит плотность. Так что знайте об этом!

Лично я использую контекст, чтобы сделать это. Это просто еще один подход, которым я хотел бы поделиться с вами

Ответ 7

Согласно Руководству по разработке Android:

px = dp * (dpi / 160)

Но часто вам нужно делать это наоборот, когда вы получаете дизайн, который указан в пикселях. Итак:

dp = px / (dpi / 160)

Если вы используете устройство с разрешением 240 точек на дюйм, это соотношение равно 1,5 (как указано выше), поэтому это означает, что значок 60 пикселей равен 40 дп в приложении.

Ответ 8

Без Context, изящные статические методы:

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

Ответ 9

Для DP to Pixel

Создайте значение в dimens.xml

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

Получите это значение в pixel как:

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

Ответ 10

Поэтому вы можете использовать следующий формулятор для вычисления правильного количества пикселей из измерения, указанного в dp

public int convertToPx(int dp) {
    // Get the screen density scale
    final float scale = getResources().getDisplayMetrics().density;
    // Convert the dps to pixels, based on density scale
    return (int) (dp * scale + 0.5f);
}

Ответ 11

Для тех, кто использует Kotlin:

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

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

Использование:

64.toPx
32.toDp

Ответ 13

использование kotlin-extension делает его лучше

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

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

ОБНОВИТЬ:

Поскольку displayMetrics является частью глобальных общих ресурсов, мы можем использовать Resources.getSystem()

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

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

Ответ 14

Это должно дать вам преобразование дп в пиксели:

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

Это должно дать вам преобразование пикселей в dp:

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

Ответ 15

Котлин

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

Ответ 16

Вероятно, лучший способ, если у вас есть измерение внутри значений /dimen, - это получить измерение непосредственно из метода getDimension(), оно вернет вам измерение, уже преобразованное в значение пикселя.

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

Чтобы лучше объяснить это,

getDimension(int resourceId) 

вернет измерение, уже преобразованное в пиксель AS FLOAT.

getDimensionPixelSize(int resourceId)

вернет то же самое, но обрезается до int, поэтому AS AN INTEGER.

Смотрите ссылка на Android

Ответ 17

Преобразование dp в пиксель.
public static int dp2px(Resources resource, int dp) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,   dp,resource.getDisplayMetrics());
}
Чтобы преобразовать пиксель в dp.
  public static float px2dp(Resources resource, float px)  {
    return (float) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, px,resource.getDisplayMetrics());
}

где ресурсом является context.getResources().

Ответ 18

вот так:

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

в зависимости от контекста, возвращаемого значения float, статического метода

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

Ответ 19

Более элегантный подход с использованием функции расширения 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()

Использование:

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

Ответ 20

Если вы разрабатываете критичное для производительности приложение, рассмотрите следующий оптимизированный класс:

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

Ответ 21

Вот как это работает для меня:

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

Вы можете сделать то же самое для ширины.

Ответ 22

чтобы конвертировать пиксели в дп используйте TypedValue.

Как указано в документации: Контейнер для динамически типизированного значения данных.

и используйте метод applyDimension:

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

который преобразует распакованное комплексное значение данных, содержащее измерение, в его окончательное значение с плавающей запятой, как показано ниже:

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

Надеюсь, это поможет.

Ответ 23

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

Ответ 24

Вы должны использовать dp так же, как и пиксели. Это все, что они есть; отображать независимые пиксели. Используйте те же номера, что и на экране со средней плотностью, и размер будет волшебным образом на экране с высокой плотностью.

Однако, похоже, что вам нужен параметр fill_parent в вашем дизайне макета. Используйте fill_parent, когда вы хотите, чтобы ваш просмотр или элемент управления расширялся до всего оставшегося размера в родительском контейнере.

Ответ 25

Много хороших решений выше. Тем не менее, лучшее решение, которое я нашел, это Google Design:

https://design.google.com/devices/

Density

Ответ 26

PX и DP являются разными, но похожими.

DP - это разрешение, когда вы определяете только физический размер экрана. Когда вы используете DP, он масштабирует ваш макет на другие экраны аналогичного размера с различными значениями плотности pixel.

Иногда вы действительно хотите pixels, хотя, когда вы имеете дело с измерениями в коде, вы всегда имеете дело с реальным pixels, если вы не конвертируете их.

Итак, на устройстве Android, нормальном размере hdpi, 800x480 is 533x320 в DP (я считаю). Чтобы преобразовать DP в pixels /1.5, чтобы преобразовать обратно *1.5. Это только для одного размера экрана и dpi, это изменится в зависимости от дизайна. Наши художники дают мне pixels, хотя и я обращаюсь к DP с вышеупомянутым уравнением 1.5.

Ответ 27

Эта работа для меня (С#):

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

Ответ 28

Если вы хотите целочисленные значения, то использование Math.round() округляет число с плавающей точкой до ближайшего целого числа.

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

Ответ 29

Котлин

   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
}

Джава

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

Ответ 30

Для Xamarin.Android

float DpToPixel(float dp)
{
    var resources = Context.Resources;
    var metrics = resources.DisplayMetrics;
    return dp * ((float)metrics.DensityDpi / (int)DisplayMetricsDensity.Default);
}

Делать это нестатичным необходимо, когда вы делаете пользовательский рендер