Формула от px до dp, от dp до px android - PullRequest
143 голосов
/ 29 ноября 2011

Я пытаюсь вычислить переменное количество пикселей для плотности независимых пикселей и наоборот.

Эта формула (px to dp): dp = (int)(px / (displayMetrics.densityDpi / 160)); не работает на небольших устройствах, потому что она делится на ноль.

Это моя формула dp to px:

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

Может кто-нибудь дать мне несколько советов?

Ответы [ 19 ]

310 голосов
/ 01 июля 2013

Примечание. Широко используемое решение основано на displayMetrics.density. Тем не менее, документы объясняют, что это значение является округленным значением, используемым с экраном «корзины». Например. на моем Nexus 10 он возвращает 2, где реальное значение будет 298dpi (реальное) / 160dpi (по умолчанию) = 1,8625.

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

[Редактировать] Это не предназначено для смешивания с внутренним модулем dp Android, поскольку, конечно, оно все еще основано на сегментах экрана. Используйте это там, где вам нужен блок, который должен отображать один и тот же реальный размер на разных устройствах.

Конвертировать дп в пиксель:

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

Преобразовать пиксель в дп:

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

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

101 голосов
/ 13 декабря 2011

Я решил свою проблему, используя следующие формулы. Пусть другие люди выиграют от этого.

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);
33 голосов
/ 29 ноября 2011

px до dp:

int valueInpx = ...;
int valueInDp= (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP, valueInpx , getResources()
                .getDisplayMetrics());
27 голосов
/ 20 февраля 2014

Просто позвоните getResources().getDimensionPixelSize(R.dimen.your_dimension), чтобы преобразовать dp единицы в пиксели

27 голосов
/ 13 января 2016

Эффективный способ когда-либо

DP в пикселях:

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

Пиксели в DP:

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

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

14 голосов
/ 19 июня 2015

Используйте эту функцию

private int dp2px(int dp) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
}
5 голосов
/ 29 ноября 2011
px = dp * (dpi / 160)

dp = px * (160 / dpi)
3 голосов
/ 26 февраля 2015

В большинстве случаев функции преобразования вызываются часто.Мы можем оптимизировать его, добавив памятку.Таким образом, он не вычисляет каждый раз, когда вызывается функция.

Давайте объявим HashMap, который будет хранить вычисленные значения.

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

Функция, которая вычисляет значения пикселей:

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

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

    }

Функция запоминания, которая возвращает значение из HashMap и поддерживает запись предыдущих значений.

Запоминание может быть реализовано различными способами в Java. Для 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 поддерживает функцию Lambda :

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

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

Спасибо.

2 голосов
/ 13 ноября 2015

Ниже функции работали хорошо для меня на всех устройствах.

Взят от 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 голосов
/ 29 ноября 2011
...