픽셀을 dp로 변환


826

해상도가 팬택 장치 인 픽셀의 높이와 너비를 사용하여 응용 프로그램을 만들었습니다 480x800.

G1 장치의 높이와 너비를 변환해야합니다.
dp로 변환하면 문제를 해결하고 두 장치에 동일한 솔루션을 제공 할 것이라고 생각했습니다.

픽셀을 DP로 변환하는 쉬운 방법이 있습니까?
어떤 제안?


1
Photoshop에서 스프라이트를 내보내는 등 일회성 변환을 수행하려는 경우 멋진 변환기가 있습니다.
Paul Lammertsma


답변:


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

332
참고 : 위는 DIP를 픽셀로 변환하는 것입니다. 원래 질문은 픽셀을 딥으로 변환하는 방법을 물었습니다!
Eurig Jones

12
OP에 대한 실제 답변은 다음과 같습니다. stackoverflow.com/questions/6656540/…
qix

119
질문에 실제로 대답하지 않을 때 답변이 더 도움이되는 방법이 재미 있습니다. -_- 질문에 대한 답변을 원한다고 생각했습니다. 정말 좋은 답변입니다. 질문이 있습니다. 에 대한 마지막 매개 변수를 applyDimension어떻게 얻을 수 있습니까? 방금 할 수 있습니까 getResource().getDisplayMetrics(), 아니면 다른 것이 있습니까?
Andy

11
참고 : 비교적 비싼 작업. 빠른 액세스를 위해 값을 캐시하십시오.
Entreco

8
에 대한 액세스 권한이없는 경우 Context객체 사용Resources.getSystem().getDisplayMetrics()
Farshad Tahmasbi

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

8
대부분의 메소드는 정수 값을 기대하므로 int Math.round (px)를 반환 할 가치가 있습니다.
Raj Labana

3
@MuhammadBabar 이것은 160dpi (mdpi)가 다른 밀도를 계산하는 기준선의 욕구이기 때문입니다. 예를 들어 hdpi는 mdpi 밀도의 1.5 배인 것으로 간주되며 실제로 240dpi를 말하는 또 다른 방법입니다. 모든 밀도에 대해서는 아래의 Zsolt Safrany의 답변을 참조하십시오.
Stephen

19
@TomTasche :에 대한 문서에서 Resource.getSystem()(강조 광산) : "시스템 자원 (응용 프로그램 자원 없음)에만 액세스 할 수 있고 현재 화면에 대해 구성되지 않은 전역 공유 자원 오브젝트를 리턴하십시오 ( 차원 단위를 사용할 수 없으며 변경되지 않음) 방향 등을 기준으로합니다. ")
Vicky Chijwani

2
개발자는 가치를 잃어 버리거나 바닥에 놓을 수 있습니다. 개발자에게 제어권을주는 것이 좋습니다.
Muhammad Nabeel Arif

7
나는 developer.android.com/reference/android/util/…DisplayMetrics.DENSITY_DEFAULT 대신에 추천 할 것이다160f
milcaepsilon

285

바람직하게는 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;
}

5
모든 장치에서 작동하지는 않습니다! 이 답변의 결과와 TypedValue.applyDimension을 사용한 결과는 OnePlus 3T에서 동일하지 않습니다 (아마도 OnePlus에 OS에 사용자 지정 배율이 내장되어 있기 때문일 수 있음). TypedValue.applyDimension을 사용하면 여러 장치에서 일관된 동작이 발생합니다.
벤 드 라 헤이

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

density 같다

  • .75켜기 ldpi( 120dpi)
  • 1.0켜기 mdpi( 160dpi; 기준선)
  • 1.5켜기 hdpi( 240dpi)
  • 2.0켜기 xhdpi( 320dpi)
  • 3.0켜기 xxhdpi( 480dpi)
  • 4.0켜기 xxxhdpi( 640dpi)

온라인 변환기 를 사용 하여 dpi 값으로 재생 하십시오 .

편집 : dpibucket과와 1 : 1 관계가없는 것 같습니다 density. Nexus 5X존재 xxhdpi는의 density값이 2.625아닌 것 같습니다 3. 장치 메트릭 에서 직접 확인하십시오 .


3
"xxhdpi 인 Nexus 5X의 밀도 값은 3이 아닌 2.6입니다."-기술적으로 Nexus 5X는 420dpi이고 Nexus 6 / 6P는 560dpi입니다. tvdpi (213dpi)가 포함 된 Nexus 7 따라서 xxdpi 및 xxxhdpi와 같은 사이트를 나열하는 사이트는 그리 멀지 않습니다. 차트는 정확하며 해당 장치는 "특수한"dpi 버킷을 기준으로 적절하게 확장됩니다.
Steven Byle

108

Context없이 이것을 사용할 수 있습니다.

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이 언급했듯이 ..이 방법을 사용하면 시스템의 밀도가 변경되면 문제가 발생할 수 있습니다. 그러니 알아 두세요!

개인적으로 나는 그것을하기 위해 컨텍스트를 사용하고 있습니다. 내가 당신과 공유하고 싶었던 또 다른 접근법 일뿐입니다.


11
이것을 사용하고 싶지 않을 수도 있습니다. getSystem ()에 대한 문서- "응용 프로그램 자원이없는 시스템 자원에만 액세스 할 수 있고 현재 화면에 대해 구성되지 않은 전역 공유 자원 오브젝트를 리턴합니다 (차원 단위를 사용할 수없고 방향에 따라 변경되지 않음). "
Stan

@Stan의 말을 둘째로 : 이것은 위험하며 특히 장치 폼 팩터가 너무 복잡해질 때 사용해서는 안됩니다.
Saket

93

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

px에서 dp는 화면 밀도에 따라 달라 지므로 모든 다른 화면 크기에서 px to dp 방법을 테스트하지 않으면 OP가 처음 120을 어떻게 얻었는지 알 수 없습니다.
John61590

75

안드로이드 개발 가이드에 따르면 :

px = dp * (dpi / 160)

그러나 종종 픽셀로 표시된 디자인을받을 때 다른 방법으로이 작업을 수행하려고합니다. 그래서:

dp = px / (dpi / 160)

240dpi 장치를 사용하는 경우이 비율은 1.5 (이전에 언급 한 것처럼)이므로 응용 프로그램에서 60px 아이콘이 40dp와 같습니다.



7
160은 일정하며 침대에 대한 답변
user25

2
@ user25 실제로 큰 답변입니다. 안드로이드 화면에서 문서를 읽지 않았습니까? 160은 안드로이드 화면 밀도에 대해 말할 때 모든 곳에서 공통적 인 상수입니다. 문서에서 인용 : "중간 밀도 (mdpi) 화면 (~ 160dpi). (기준 밀도입니다)". 어서, 남자
mykolaj

70

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

24
Resources.getSystem()javadoc은 "응용 프로그램 자원이없는 시스템 자원에만 액세스 할 수 있고 현재 화면에 대해 구성되지 않은 전역 공유 자원 오브젝트를 리턴합니다 (차원 단위를 사용할 수없고 방향에 따라 변경되지 않음"). 이것은 어떻게 든 작동 하더라도이 작업을 수행해서는 안된다고 말합니다.
Austyn Mahoney

방금 @AustynMahoney의 의견을 읽고이 답변이 원래 생각했던 것만 큼 훌륭하지 않다는 것을 깨달았습니다. 그렇지만 공의회를 취소 할 수는 없습니다 ! 아아!
Vicky Chijwani

45

에 대한 DP to Pixel

에 가치 창출 dimens.xml

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

그 값을 다음 pixel과 같이 얻으십시오 .

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

39

따라서 다음 공식을 사용하여 dp에 지정된 차원에서 올바른 픽셀 수를 계산할 수 있습니다

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

4
이것은 dp를 픽셀로 변환하지만 메소드를 호출했습니다 convertToDp.
Qwertie

4
+ 0.5F 여기 설명입니다 -> developer.android.com/guide/practices/... . 가장 가까운 정수로 반올림하는 데 사용됩니다.
Bae


web.archive.org/web/20140808234241/http://developer.android.com/… 여전히 문제의 콘텐츠가있는 링크
caw

39

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

Resource.getSystem ()에 대한 문서에서 : "시스템 자원 (응용 프로그램 자원 없음)에만 액세스 할 수 있고 현재 화면에 대해 구성되지 않은 전역 공유 자원 오브젝트를 리턴하십시오 (차원 단위를 사용할 수 없으며 다음을 기반으로 변경되지 않음) 방향 등) "
HendraWD

@HendraWD 문서가 혼동 될 수 있습니다. 언급 한 차원 단위는 응용 프로그램 수준의 차원의 리소스입니다. displayMetrics는 응용 프로그램 수준의 리소스가 아닙니다. 시스템 자원이며 올바른 값을 리턴합니다. 이 코드는 모든 Prod 앱에서 제대로 작동합니다. 문제가 없었습니다.
Gunhan

33

안드로이드 SDK에는 기본 유틸리티가 있습니다 : http://developer.android.com/reference/android/util/TypedValue.html

float resultPix = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,getResources().getDisplayMetrics())

이것을 사용해야합니다. 보너스로 SP도 수행합니다.
Mark Renouf

2
resultPixint 유형이어야합니다. int resultPix = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,getResources().getDisplayMetrics())
vovahost

27

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()

4
왜 이것을 Int의 확장으로 추가하겠습니까? 책임은 Int 유형으로 아무것도 할 필요가 없습니다.
htafoya

19

이것은 dp를 픽셀로 변환합니다 :

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

19

코 틀린

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

12

아마도 치수 / 값에 치수가있는 경우 가장 좋은 방법은 getDimension () 메서드에서 직접 치수를 얻는 것입니다. 이미 픽셀 값으로 변환 된 치수를 반환합니다.

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

이것을 더 잘 설명하기 위해

getDimension(int resourceId) 

FLOAT로 이미 픽셀로 변환 된 치수를 반환합니다.

getDimensionPixelSize(int resourceId)

동일하지만 int로 잘린 상태로 반환되므로 INTEGER 그대로.

안드로이드 참조 보기


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

여기서 resource는 context.getResources ()입니다.


8
픽셀을 dp로 변환하지 않기 때문에 대답이 잘못되었습니다. 픽셀을 픽셀로 변환합니다!
Yaroslav

px2dp가 잘못되었습니다. 동일한 값을 픽셀 단위로 반환합니다.
natario

8

이처럼 :

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 값 반환, 정적 메소드

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


8

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

확장 사용을 좋아합니다. function name이 경우에는 "역시 변환"기능을 거꾸로 읽습니다 . 각 함수의 의도를 명확히하기 위해 dpToPx 및 pxToDp를 각각 읽도록 함수 이름을 업데이트 할 수 있습니다.
Maxwell

Resource.getSystem ()에 대한 문서에서 : "시스템 자원 (응용 프로그램 자원 없음)에만 액세스 할 수 있고 현재 화면에 대해 구성되지 않은 전역 공유 자원 오브젝트를 리턴하십시오 (차원 단위를 사용할 수 없으며 다음을 기반으로 변경되지 않음) 방향 등) "
HendraWD

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

2
이 질문에 대한 다른 많은 답변에서 다루는 것과 동일하지 않습니까?
TZHX

7

성능이 중요한 응용 프로그램을 개발하는 경우 다음 최적화 클래스를 고려하십시오.

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

그것은 당신이 정말로 자주 변환을 할 때만 말이됩니다. 제 경우에는 그렇습니다.
Pavel

160f는 무엇입니까? 왜 사용합니까, 왜 160입니까?
dephinera

160 => 160dpi와 이는 화학식 변환 대책 인
xAqweRx

6

픽셀을 dp로 변환하려면 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());

희망이 도움이됩니다.


6

이것이 나를 위해 작동하는 방법입니다.

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

너비에 대해서도 동일한 작업을 수행 할 수 있습니다.



4

픽셀처럼 dp를 사용해야합니다. 그것이 전부입니다. 독립 픽셀을 표시합니다. 중간 밀도 화면에서와 같은 숫자를 사용하면 고밀도 화면에서 크기가 마술처럼 정확합니다.

그러나 레이아웃 디자인의 fill_parent 옵션이 필요한 것 같습니다. 뷰 또는 컨트롤을 부모 컨테이너의 나머지 모든 크기로 확장하려면 fill_parent를 사용하십시오.


실제로 내 문제는 내 응용 프로그램이 고밀도 화면으로 코딩되어 이제는 저밀도 화면으로 변환해야한다는 것입니다.
Indhu

중간 밀도 화면의 픽셀을 수정하고 (에뮬레이터에서 중간 밀도 화면을 설정할 수 있음) 픽셀을 dp로 바꿉니다. 그러나 fill_parent 및 여러 레이아웃을 사용하여보다 유연한 응용 프로그램을 만들 수 있습니다.
Michael Lowman

마지막으로, 나는 모든 px를 dp로 수동으로 변경하는 것 외에는 옵션이 없었습니다. : :(
Indhu

1
적어도 다음에는 dp를 먼저 사용하고 아무것도 변경할 필요가 없습니다 :) 대부분의 경우 절대 위치 지정이 필요없는 레이아웃을 사용할 수는 있지만
Michael Lowman

내 첫 번째 응용 프로그램 이었기 때문에 ... 나는 ... :) 내가 다시하지 않을 것이다 ...이 실수를
Indhu

4

PXDP다르지만 비슷합니다.

DP화면의 실제 크기 만 고려할 때의 해상도입니다. 사용 DP하면 pixel밀도 가 다른 다른 비슷한 크기의 화면으로 레이아웃이 조정됩니다 .

때로는 실제로 원 pixels하지만 코드에서 치수를 처리 할 때 pixels변환하지 않는 한 항상 real을 처리 합니다.

따라서 안드로이드 장치, 보통 크기의 hdpi화면 800x480 is 533x320에서 DP(믿습니다). 변환하려면 DPpixels /1.5다시 변환 할 *1.5. 이것은 한 화면 크기에만 dpi적용되며 디자인에 따라 달라집니다. 우리 예술가들은 나에게 줄 것이고 위의 방정식으로 pixels변환합니다 .DP1.5


3

정수 값을 원하면 Math.round ()를 사용하면 부동 소수점을 가장 가까운 정수로 반올림합니다.

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

2

이것은 나를 위해 일했습니다 (C #).

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

이 질문에 대한 대답은 아니지만 C #에서는 작동합니다. 감사합니다
Yekmer Simsek

2

코 틀린

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

2

가장 좋은 대답은 안드로이드 프레임 워크 자체에서 나옵니다.이 평등을 사용하십시오 ...

public static int dpToPixels(final DisplayMetrics display_metrics, final float dps) {
    final float scale = display_metrics.density;
    return (int) (dps * scale + 0.5f);
}

(dp를 px로 변환)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.