밀도 독립 픽셀과 그 반대로 가변 픽셀 양을 계산하려고합니다.
이 수식 (px to dp): dp = (int)(px / (displayMetrics.densityDpi / 160));
은 0으로 나뉘어져 있기 때문에 소형 장치에서는 작동하지 않습니다.
이것은 내 dp to px 공식입니다.
px = (int)(dp * (displayMetrics.densityDpi / 160));
누군가 나에게 포인터를 줄 수 있습니까?
밀도 독립 픽셀과 그 반대로 가변 픽셀 양을 계산하려고합니다.
이 수식 (px to dp): dp = (int)(px / (displayMetrics.densityDpi / 160));
은 0으로 나뉘어져 있기 때문에 소형 장치에서는 작동하지 않습니다.
이것은 내 dp to px 공식입니다.
px = (int)(dp * (displayMetrics.densityDpi / 160));
누군가 나에게 포인터를 줄 수 있습니까?
답변:
참고 : 위의 널리 사용되는 솔루션은를 기반으로 displayMetrics.density
합니다. 그러나 문서에서는이 값이 반올림 값이며 화면 '버킷'과 함께 사용된다고 설명합니다. 예 : 내 Nexus 10에서는 2를 반환하며 실제 값은 298dpi (실제) / 160dpi (기본값) = 1.8625입니다.
요구 사항에 따라 다음과 같이 달성 할 수있는 정확한 변환이 필요할 수 있습니다.
[편집] 이것은 여전히 스크린 버킷을 기반으로하기 때문에 안드로이드의 내부 dp 유닛과 혼합되어서는 안됩니다. 다른 장치에서 동일한 실제 크기를 렌더링해야하는 장치를 원하는 경우이 옵션을 사용하십시오.
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());
typedValue.applyDimension( TypedValue.COMPLEX_UNIT_PX, valueInDp , getResources() .getDisplayMetrics());
으로 PX에서 DP로, 이것은 또한 가장 좋은 답변입니다
applyDimension
픽셀 만 산출합니다. android.googlesource.com/platform/frameworks/base/+/refs/heads/…를 참조하십시오 . 여기서 전환이 수행되지 않습니다 COMPLEX_UNIT_PX
.
dp
. 소스 코드를 보면, 경우에 대해 TypedValue.COMPLEX_UNIT_DIP
, value * metrics.density
당신이 실제로 필요로하는 곳에, 반환됩니다 value * metrics.density
. 그래서 당신이 valueInDp`을 getting`하는 것은 아닙니다 dp
위한 valueInPx
에서 px
.
value / metrics.density
"
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);
}
이것이 도움이되기를 바랍니다.
displayMetrics.xdpi
모든 장치에서 다른 것을 사용하기 때문에 . 안타깝게도이 잘못된 답변에는 추가 의견이 가장 많습니다.
private fun dpToPx(dp: Int) = (dp * Resources.getSystem().displayMetrics.density).toInt()
이 기능 사용
private int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
}
px = dp * (dpi / 160)
dp = px * (160 / dpi)
(displayMetrics.densityDpi / 160)
-이 부분은 작은 장치에서 0을 얻을 수 있습니다. 예를 들어 계산 120/160
하면 두 값이 모두 int이므로 0이됩니다 (int) (px/0)
.
대부분의 경우 변환 함수가 자주 호출됩니다. 메모를 추가하여 최적화 할 수 있습니다. 따라서 함수가 호출 될 때마다 계산하지 않습니다.
계산 된 값을 저장할 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));
}
감사.
아래 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);
}
DP, SP, 인치, 밀리미터, 포인트 또는 픽셀을 다른 화면 밀도에서 서로 변환하는 온라인 계산기를 찾고 있다면 이것이 내가 아는 가장 완벽한 도구입니다 .
// 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));
}
다음 Kotlin 확장을 사용하십시오.
/**
* Converts Pixel to DP.
*/
val Int.pxToDp: Int
get() = (this / Resources.getSystem().displayMetrics.density).toInt()
/**
* Converts DP to Pixel.
*/
val Int.dpToPx: Int
get() = (this * Resources.getSystem().displayMetrics.density).toInt()
위에 허용 된 답변이 완전히 정확하지 않습니다. 안드로이드 소스 코드를 검사하여 얻은 정보에 따르면 :
Resources.getDimension()
그리고 getDimensionPixelOffset()
/ getDimensionPixelSize()
는 전자가 돌아가고 float
두 번째는 같은 값을 int
적절히 반올림 한다는 점에서만 다릅니다 . 이들 모두에 대해 반환 값은 원시 픽셀입니다.
세 가지 함수는 모두 , 및 을 호출 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