Формула px для dp, dp для px android
Я пытаюсь вычислить количество пикселей в плотность независимых пикселей и наоборот.
эта формула (px to dp): dp = (int)(px / (displayMetrics.densityDpi / 160));
не работает на небольших устройствах, потому что он делится на ноль.
Это моя формула dp to px:
px = (int)(dp * (displayMetrics.densityDpi / 160));
может кто-нибудь дать мне несколько советов?
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 к 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);
px к 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);
}
пиксель в 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());
}
В большинстве случаев, функции преобразования называются часто. Мы можем оптимизировать его, добавив мемоизация. Значит,не все-время вычисления функции.
давайте объявим 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;
}
функция 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));
}
спасибо.
ниже funtions работал хорошо для меня на разных устройствах.
он взят из 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]
и определите плотность экрана. Что-то вроде этого:--3-->
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. Для всех из них возвращаемое значение находится в пикселях raw.
все три функции implementedy по телефону 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) ;
}