Формула РХ на DP, DP в px для Андроид


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

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

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

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

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

18 137

18 ответов:

Примечание: широко используемое решение выше основано на displayMetrics.density. Однако документы объясняют, что это значение является округленным значением, используемым с экраном "ведра". Например. на моем Nexus 10 он возвращает 2, где реальное значение будет 298dpi (real) / 160dpi (default) = 1.8625.

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

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

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

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

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

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

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

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

dp to px:

displayMetrics = context.getResources().getDisplayMetrics();
return (int)((dp * displayMetrics.density) + 0.5);

px to dp:

displayMetrics = context.getResources().getDisplayMetrics();
return (int) ((px/displayMetrics.density)+0.5);

px to dp:

int valueInpx = ...;
int valueInDp= (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP, valueInpx , getResources()
                .getDisplayMetrics());

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

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

DP в пиксель:

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

Pixel to DP:

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

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

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

private int dp2px(int dp) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
}
px = dp * (dpi / 160)

dp = px * (160 / dpi)

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

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

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;

    }

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

Memoization может быть реализованы по-разному в 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));
}

спасибо.

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

он взят из 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);
}

// для получения в терминах Decimal / Float

public static float convertPixelsToDp(float px, Context context) {

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



public static float convertDpToPixel(float dp, Context context) {
    DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
    float px = dp * (metrics.densityDpi / 160f);
    return Math.round(px);
}


// for  getting in terms of Integer

private int convertPxToDp(int px, Context context) {
    Resources resources = context.getResources();
    return Math.round(px / (resources.getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
}


private int convertDpToPx(int dp, Context context) {
    Resources resources = context.getResources();

    return Math.round(dp * (resources.getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));

}

________________________________________________________________________________

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


private int convertDpToPx(int dp){
    return Math.round(dp*(getResources().getDisplayMetrics().xdpi/DisplayMetrics.DENSITY_DEFAULT));

}

private int convertPxToDp(int px){
    return Math.round(px/(Resources.getSystem().getDisplayMetrics().xdpi/DisplayMetrics.DENSITY_DEFAULT));
}

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

можно использовать [DisplayMatrics][1] и определить плотность экрана. Что-то вроде этого:

int pixelsValue = 5; // margin in pixels
float d = context.getResources().getDisplayMetrics().density;
int margin = (int)(pixelsValue * d);

Как я помню, лучше использовать настил для смещений и округления по ширине.

Не стесняйтесь использовать этот метод, я писал:

int dpToPx(int dp)
{
    return (int) (dp * getResources().getDisplayMetrics().density + 0.5f);
}

ответ, принятый выше, не является полностью точным. Согласно информации, полученной при проверке исходного кода Android:

Resources.getDimension() и getDimensionPixelOffset()/getDimensionPixelSize() отличаются только тем, что первый возвращает float в то время как последние два возвращают одно и то же значение, округленное до int appropriatelly. Для всех из них возвращаемое значение находится в необработанных пикселях.

все три функции реализуются путем вызова Resources.getValue() и преобразование полученного таким образом TypedValue по телефону TypedValue.complexToDimension(), TypedValue.complexToDimensionPixelOffset() и TypedValue.complexToDimensionPixelSize(), соответственно.

поэтому, если вы хотите получить "сырое" значение вместе с единицей, указанной в источнике XML, вызовите Resources.getValue() и использовать методы TypedValue класса.

DisplayMetrics displayMetrics = contaxt.getResources() .getDisplayMetrics ();

    int densityDpi = (int) (displayMetrics.density * 160f);
    int ratio = (densityDpi / DisplayMetrics.DENSITY_DEFAULT);
    int px;
    if (ratio == 0) {
        px = dp;
    } else {
        px = Math.round(dp * ratio);

    }

вариация на ct_robs ответ выше, если вы используете целые числа, что не только позволяет избежать деления на 0 он также дает полезный результат на небольших устройствах:

в целочисленных вычислениях, включающих деление для наибольшей точности, сначала умножьте перед делением, чтобы уменьшить эффекты усечения.

px = dp * dpi / 160 dp = px * 160 / dpi

5 * 120 = 600 / 160 = 3

вместо

5 * (120 / 160 = 0) = 0

Если вы хотите округленный результат сделать это

px = (10 * dp * dpi / 160 + 5) / 10 dp = (10 * px * 160 / dpi + 5) / 10

10 * 5 * 120 = 6000 / 160 = 37 + 5 = 42 / 10 = 4

С помощью других ответов я написал эту функцию.

public static int convertToPixels(Context context, int nDP)
{
        final float conversionScale = context.getResources().getDisplayMetrics().density; 
        return (int) ((nDP * conversionScale) + 0.5f) ;
}