프로그래밍 방식으로 안드로이드 화면 크기를 한 번에 얻는 방법?


132

터치 이벤트 및 뷰 측정 / 레이아웃에 사용되는 단위에서 프로그래밍 방식으로 화면 크기를 어떻게 알 수 있습니까? 즉, 터치 이벤트 ' getRawX()/getRawY()및에 의해 사용되는 좌표계에서 화면 오른쪽 하단 모서리의 좌표를 원합니다 View.getLocationOnScreen().

다양한 모드의 전화기에 여러 가지 "픽셀"개념이 있기 때문에 원하는 이벤트 / 뷰 단위를 "픽셀"이라고 부르는 것이 주저하며 일관된 이야기를 추가하지는 않습니다.

나는 이것이 stackoverflow 및 다른 곳에서 많이 요청되고 답변 된 것을 보았지만 아무것도 없었다. 모든 모드에서 내 전화 (droid 4, android 4.1.2)에서 실제로 응답하는 것은 .

(와!)

이것은 앱이 "화면 호환성 모드"(예 : 매니페스트의 targetSdkVersion <= 10)인지 여부에 관계없이 작동해야하는 라이브러리 코드 용이며 위치, 크기에 대한 가정도하고 싶지 않습니다. 또는 상태 표시 줄 또는 기타 유사한 화면 장식이 있습니다.


사실은 다음과 같습니다.

  1. 내 휴대 전화 (Android 4.1.2를 실행하는 droid 4)에는 540x960 물리적 픽셀, 즉 작은 색의 빛나는 점이 있습니다.

  2. 터치 이벤트 및 측정보기에서 원하는 단위의 화면 크기는 앱이 화면 호환 모드에있을 때 360x640, 앱이 화면 호환 모드에 있지 않을 때 540x960입니다. 터치 이벤트 또는 뷰를 찾지 않고 프로그래밍 방식으로 찾아야하는 숫자이지만이 숫자를 반환하는 API를 찾는 데 어려움이 있습니다.

  3. 다양한 방식으로 얻은 Display 및 DisplayMetrics 객체는 모두 화면 크기가 540x960 "픽셀"이라고 주장합니다 (화면 호환성 모드에 관계없이). 구체적으로 말하면, DisplayMetrics. {width, height} 픽셀, Display.getSize (), Display.getRealSize (), Display.get {Width, Height} (),

  4. 다양한 방법으로 얻은 구성 객체는 모두 screen {Width, Height} Dp = 360x614 (화면 compat 모드인지 여부)를 말합니다. 가로 세로 비율이 잘못 되었기 때문에 전체 화면을 나타내는 것은 아닙니다. (전체 화면에서 상태 표시 줄을 뺀 것으로 생각합니다. 전체 화면이 필요합니다.) 640을 반환하는 API를 모르더라도 전체 화면이 360x640dp라고 말하는 것이 안전하다고 생각합니다.

  5. 다양한 방법으로 얻은 DisplayMetrics는 화면 밀도 모드에서는 "밀도"가 1.0f이고, 화면 모드에서는 그렇지 않은 경우 1.5f입니다.

  6. 액티비티 getWindow().getAttributes().{width,height} 는 일반적으로 MATCH_PARENT 실제 크기 가 아니라 포함되므로 도움이되지 않습니다 . 그러나 나는 분명히에서 원하는 답변을 얻을 수있는 활동의 getWindow().getDecorView().getMeasured{Width,Height}() (실제로 활동의 창의 decorView하지 않기 때문에 놀라운 보고 가 전체 화면을 차지 것처럼, 그것은 화면을 뺀 상태 표시 줄을 복용 것 같습니다). 그러나 창 크기가 조정되면 (소프트 키보드가 나타납니다. 누군가 window.setAttributes ()를 호출하거나 누군가가 활동에 있지 않은 경우), 이것은 분명히 모든 것이 될 것이기 때문에 이것에 의존하고 싶지 않습니다. 잘못된.

다음 공식을 유지해야한다는 것을 이해합니다 .pixels = dp * density 그렇지 않은 경우보고 된 모든 숫자 ((3), (4), (5))와 일치하는 것 같습니다 화면 호환성 모드 : 540x960 = 360x640 * 1.5 그러나 화면 호환성 모드에서는 합산되지 않습니다. 540x960! = 360x640 * 1 따라서 무언가가 잘못되었습니다.

가장 간단한 설명은 위의 (3)에 나열된 방법이 화면 호환 모드에서 "픽셀"에 대한 잘못된 답변을 제공한다는 것입니다. 즉, 360x640 "픽셀"을 반환하려고했지만 잘못되었습니다. 대신 540x960을 반환합니다. 그러나 다른 방법으로 볼 수도 있습니다.

어쨌든, 위의 퍼즐 조각에서 모드에 관계없이 원하는 숫자를 얻는 것은 확실히 까다로운 퍼즐입니다. 두 가지 모드 모두에서 휴대 전화에서 작동하는 것처럼 보이는 방법을 찾았지만 매우 회로가 뛰어나고 여전히 다소 흔들리는 것처럼 보이는 두 가지 가정에 의존합니다 (아래 코드 주석에 설명).

여기 내 레시피가 있습니다 :

/** get screen size in "pixels", i.e. touchevent/view units.
* on my droid 4, this is 360x640 or 540x960
* depending on whether the app is in screen compatibility mode
* (i.e. targetSdkVersion<=10 in the manifest) or not. */
public void getScreenSizePixels(int widthHeightInPixels[/*2*/])
{
    Resources resources = getResources();
    Configuration config = resources.getConfiguration();
    DisplayMetrics dm = resources.getDisplayMetrics();
    // Note, screenHeightDp isn't reliable
    // (it seems to be too small by the height of the status bar),
    // but we assume screenWidthDp is reliable.
    // Note also, dm.widthPixels,dm.heightPixels aren't reliably pixels
    // (they get confused when in screen compatibility mode, it seems),
    // but we assume their ratio is correct.
    double screenWidthInPixels = (double)config.screenWidthDp * dm.density;
    double screenHeightInPixels = screenWidthInPixels * dm.heightPixels / dm.widthPixels;
    widthHeightInPixels[0] = (int)(screenWidthInPixels + .5);
    widthHeightInPixels[1] = (int)(screenHeightInPixels + .5);
}

화면 크기를 찾는 더 나은 / 깨끗한 방법이 있습니까 ??


29
+1 좋은 질문이며 많은 연구 노력을 보여줍니다.
Alex Gittemeier

1
@Don docs 에서는 호환 모드가 이전 설정에서 "확대 / 축소"작업을 중지한다고 설명합니다. 그러나 귀하의 관찰에 따르면 "작동 방식"에 대해서는 명확하게 설명되어 있지 않습니다. 간단히 밀도 스케일링을 해제한다고 생각합니다. 즉, 1px는 1dp가됩니다. 이 변경 사항은 렌더링 부분에만 적용되며 DisplayMetrics이러한 변경 사항은 업데이트되지 않을 수 있습니다. 같은 문제가 있습니다 이미 제기는.
SD

@ user117-흥미 롭습니다. 음의 부분 DisplayMetrics의 1.0로 변경 least-- 밀도로 업데이트되었다. 그러나 widthPixels / heightPixels는 일치하도록 변경되지 않았습니다. 인용 된 문제와 관련하여, 동작이 3.1 동작으로 되돌아 간 것처럼 보입니다 (즉, heightPixels 에 상태 표시 줄이 포함 된 것을보고 있습니다 . 그러나 잘못된 단위 인 것 같습니다)
Don Hatch

@DonHatch 감사합니다. 친절하게-실제로 StackExchange에서 환영받지 못하는 사려 깊은 질문에 칭찬을 주려고했습니다. '실제'보다 많은 질문이 어떻게 대답에 아무것도 얻지 못했는지에 주목하십시오. ) 주제에 대한 청중의 지식의 질. 지금, 나는 "실제"가 아니기 때문에 내 자신의 질문이 차례로 닫히면 서 외상을 입을 수 있고, 유머 감각이 나에게 실패 할 수도 있지만, "좋은"받는 대답이 실제로있는 질문처럼 보이기 시작합니다. 어떤이 모두 여기에 대해이됩니다 ... 그리고 물론, 내가 당신 : upvoted
mlvljr

btw! 내 의심의 라인을 따라 여기의 무엇인가 : michael.richter.name/blogs/...는 (. ESP, 신속하게 제작 된 답변에 하나 자신의 (1) 지점을 참조 -이 Q와 실제로 단지의 경우를!). 어쨌든 해피 뉴욕 (11 분 안에 광산이 온다)! :)
mlvljr

답변:


41
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;

이제 모든 버튼, 텍스트 뷰 등이이 단위로 측정되므로 센티미터보다 더 나은 측정 단위 인 픽셀 단위로 화면 크기를 측정 할 수 있습니다. 내가 정상적으로 사용하는 것


3
Op (특히 지점 # 3)에 따르면, 화면 모드에서 이것이 올바르지 않습니까?
Tom

9

DisplayMetrics를 사용하면 모든 장치의 화면 높이와 너비를 얻을 수 있습니다. 너비와 높이는 회전에 민감합니다. 여기 코드가 있습니다.

DisplayMetrics metrics; 
int width = 0, height = 0;

onCreate 메소드에서

 metrics = new DisplayMetrics();        
 getWindowManager().getDefaultDisplay().getMetrics(metrics);

 height = Math.min(metrics.widthPixels, metrics.heightPixels); //height
 width = Math.max(metrics.widthPixels, metrics.heightPixels); //width

이 시도.


2
아니요, (3)에서 말했듯이 메트릭스. {width, height} 화면 호환성 모드에서 픽셀이 올바른 답변을 제공 하지 않습니다 .
Don Hatch

또한 나는 발견했다 : 그것은 가벼운 메트릭스처럼 보인다. 높이 픽셀은 화면이 회전하고 그 반대의 경우에 너비를 줄 수 있습니다!
JohnyTex

8

# 6에서 DecorView가 원하는 것을 제공하는 것처럼 보이지만 실현 가능하다고 생각하지는 않습니다. 나는 그것이 당신이 올 수있는 한 가까이 있다고 믿습니다. 에 대한 문서에 따르면 Window.getDecorView:

창 관리자에 창으로 추가 할 수있는 최상위 창 장식보기 (표준 창 프레임 / 장식 및 그 안의 클라이언트 내용 포함)를 검색합니다.

상태 표시 줄은 여기에 언급 된 창 장식의 일부입니다. 소프트웨어 키보드 및 기타 오버레이는 자체 창을 수신하므로 관련 값을 방해하지 않아야합니다. 디스플레이 메트릭이 정확하지 않은 것은 맞지만 응용 프로그램이 전체 화면 인 경우 호환성 변환기를 통해 항상 전체 화면 크기를 필터링해야합니다. 다른 응용 프로그램은 귀하의 응용 프로그램에 액세스 할 수 없습니다Window 동안 속성을 변경하는 것에 대해 걱정할 필요가 없습니다.

희망이 도움이됩니다.


5

나는 이것을 의견으로 써야하지만 그에 대한 담당자는 없습니다.
이것은 완전히 정답은 아니지만 DisplayMetrics 메서드에서 높이와 너비를 전환했을 때 치수를 얻었습니다.

    DisplayMetrics metrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(metrics);   
    width = metrics.heightPixels;
    height = metrics.widthPixels;

내가 말했듯이 이것은 정확하지 않을 수도 있지만 왜 그런지 모르겠지만 그것이 효과가있었습니다.


화면이 회전했기 때문입니다.
JohnyTex

날 믿지 않았어
abhyudayasrinet


3

피타고라스 정리를 사용하여 Android 전화 / 태블릿 화면의 대각선 크기를 찾았습니다. 동일한 주체가 iPhone 또는 Blackberry 화면에 적용될 수 있습니다.

DisplayMetrics met = new DisplayMetrics();                
this.getWindowManager().getDefaultDisplay().getMetrics(met);// get display metrics object
String strSize = 
new DecimalFormat("##.##").format(Math.sqrt(((met.widthPixels / met.xdpi) *
(met.widthPixels / met.xdpi)) +
((met.heightPixels / met.ydpi) * (met.heightPixels / met.ydpi))));
// using Dots per inches with width and height

피타고라스는 천재 였을 것입니다. 그는 수년 전에 스마트 폰 프로그래밍을 알고있었습니다.


1

아래 방법을 사용하여 장치의 너비를 얻습니다.

public static int getDeviceWidth(Context context){
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    int width=display.getWidth();
    return width;
}

이 방법은 더 이상 사용되지 않습니다. displaymetrics 방법을 사용하십시오.
Simon

0

이 기능은 단순히 안드로이드 화면 크기의 너비와 높이를 얻는 데 도움이 될 것이라고 생각합니다. 이 함수는 아래와 같이 너비와 높이를 정수 배열로 반환합니다.

private int[] getScreenSIze(){
        DisplayMetrics displaymetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        int h = displaymetrics.heightPixels;
        int w = displaymetrics.widthPixels;

        int[] size={w,h};
        return size;

    }

create 메소드에서 너비와 높이를 아래와 같이 출력하십시오.

 int[] screenSize= getScreenSIze();
        int width=screenSize[0];
        int height=screenSize[1];
        screenSizes.setText("Phone Screen sizes \n\n  width = "+width+" \n Height = "+height);

소스 코드를 다운로드 하여 Android 스튜디오에서 테스트하십시오.


0

이것은 나를 위해 작동합니다 :

int width = Resources.getSystem (). getDisplayMetrics (). widthPixels;

int height = Resources.getSystem (). getDisplayMetrics (). heightPixels;

가로 리사이클 뷰에서 항목 너비를 업데이트하는 데 사용했습니다. (필요에 따라) 누군가에게 도움이되기를 바랍니다.


-1

Kotlin 의이 솔루션에 대해 다음을 시도하십시오.

private fun yourFunction(){
   val metrics = DisplayMetrics()
   windowManager.defaultDisplay.getMetrics(metrics)
   val width = metrics.widthPixels
   val height = metrics.heightPixels
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.