개발을 하다 보면 에뮬레이터 혹은 내 휴대폰의 화면 크기를 구할 일이 가끔 생긴다.
얼마 전, 함께 프로젝트를 하는 디자이너가 내 휴대폰 화면 사이즈를 물어보았다.
이전에 화면의 가로 사이즈 구하는 코드를 사용해본 적이 있었기 때문에 후딱 로그 찍어서 알려주었다.
그리고 디자이너에게 질문이 하나 왔는데..
이거 세로 사이즈 상태 바랑 네비게이션 바 포함된건가요?
어..? 뇌절이 왔다.
생각해보니 이전에는 가로 사이즈만 사용해봐서 측정된 세로 사이즈가 정확히 어디부터 어디까지인지 몰랐다.
그리고 이 과정에서 알게 된 안드로이드의 화면 크기 구하는 방법이다.
val display = this.applicationContext?.resources?.displayMetrics
val deviceWidth = display?.widthPixels
val deviceHeight = display?.heightPixels
자 deviceWidth와 deviceHeight를 Log 찍어보자
아, 그전에 저렇게 구하면 픽셀 값이 나오니 mdpi 기준 dp값으로 바꾸는 코드를 알아보자.
fun px2dp(px: Int, context: Context) = px / ((context.resources.displayMetrics.densityDpi.toFloat()) / DisplayMetrics.DENSITY_DEFAULT)
아래 코드와 같은 의미이다.
fun px2dp(px: Int, context: Context): Float {
return px / ((context.resources.displayMetrics.densityDpi.toFloat()) / DisplayMetrics.DENSITY_DEFAULT)
}
위에서 구한 deviceWidth와 deviceHeight를 px2dp 함수의 px 매개변수로 넘겨준다.
Log.d("deviceSize", "${px2dp(deviceWidth!!, this)}")
Log.d("deviceSize", "${px2dp(deviceHeight!!, this)}")
내 휴대폰의 경우 갤럭시S21+이고
px2dp를 적용하기 전 픽셀 값
width : 1080, height : 2181
px2dp함수를 적용한 dp값
width : 360, height : 727
갤럭시S21+의 공식 픽셀 값
width: 1080, height: 2400
어라? 뭔가 이상하지 않은가?
가로는 맞는 것 같은데.. 세로는 내가 측정한 픽셀 값과 공식 픽셀 값이 맞지 않는다.
dp값 또한 애매하게 727이다. 적어도 10의 자리로 떨어지게 만들었을 것 같은데 말이다.
여기서 생각해볼 수 있는 것은 상태 바(status bar)와 네비게이션 바(navigation bar)이다.
상태 바(status bar)란 휴대폰의 맨 위에 시간, 알림, 블루투스, 와이파이 배터리 등의 정보를 보여주는 영역이다. (아래 사진과 같은~)
네비게이션 바(navigation bar)란 아이폰에는 없지만 안드로이드 기기에 있는 최근 사용 앱, 홈, 뒤로가기
버튼이 있는 최하단 영역이다.
최근에는 갤럭시에서도 스와이프 제스쳐를 지원하면서 네비게이션 바를 없애고 제스쳐를 이용할 수 있다. (점점 사용하는 사람들도 늘어나고 있다.)
스와이프 제스쳐 네비게이션 바다시 화면의 크기를 찾는 내용으로 돌아와보자.
그럼 2400-2181=219
는 어디로간걸까
일단 단위가 커서 계산하기 귀찮으니 dp값으로 변환해서 생각하자
2400을 px2dp함수에 넣어 계산하면 800이 나온다.
그럼? 이제 800-727=73
이 어디로 갔는지 찾으면 된다.
근데 여기서의 문제는 73
에 상태 바와 네비게이션 바가 모두 포함된 것인지 하나만 포함된 것인지를 모르겠다는 것이었다.
그래서 구글링한 결과 상태 바를 구하는 코드는 아래와 같다.
fun getStatusBarHeight(context: Context){
var statusbarHeight = 0
val resourceId: Int = context.resources.getIdentifier("status_bar_height", "dimen", "android")
if (resourceId > 0) {
statusbarHeight = resources.getDimensionPixelSize(resourceId)
Log.d("deviceSize", "status bar : ${px2dp(statusbarHeight, context)}")
}
}
이러면 로그에 상태 바의 세로 dp값이 나올 것이다.
내 휴대폰은(갤럭시S21+) 25
가 나왔다.
그럼 727 + 25 < 800
로 아직 부족하다.
여기서 부족한 부분은 네비게이션 바로 추측해볼 수 있다.
그럼 이제 네비게이션 바의 크기를 측정해보자!
네비게이션 바의 세로 길이를 구하는 코드는 아래와 같다.
fun getnavigationBarHeight(context: Context){
val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
var navigationbarHeight = 0
if (resourceId > 0) {
navigationbarHeight = resources.getDimensionPixelSize(resourceId)
Log.d("deviceSize", "navigation bar : ${px2dp(navigationbarHeight, context)}")
}
}
상태 바 구하는 코드와 거의 유사하다
내 휴대폰의(갤럭시S21+) 네비게이션 바 세로 dp값은 48
이 나왔다.
727 + 25 + 48 = 800
이제 드디어 숫자가 딱 맞았다.
상태 바와 네비게이션 바를 제외한 실직적인 앱 화면 크기는 727
상태 바와 네비게이션 바를 합친 디바이스의 화면 크기는 800
이다.
혹시 그럼 스와이프 제스쳐를 쓰면 어떻게 되죠?
추가로 궁금해서 네비게이션 바를 스와이프 제스쳐로 바꾸고 다시 측정해보았다.
그럼 스와이프 제스쳐의 경우 하단 영역의 길이가 15
로 나온다.
스와이프 제스쳐가 차지하는 하단 영역이 없는 줄 알았지만 측정하고 자세히보니 정말 얇은 영역이 있었다.
760 + 25 + 15 = 800
으로 네비게이션 바를 사용할 때보다 꽤 많은 영역이 늘어난다는 것을 알 수 있다.
방금의 결론에서 우리가 맨 처음 구했던 deviceHeight
는
디바이스 크기 - 상태바 - 네비게이션바
였다.
하지만 다른 상황이 있다.
위 경우는 상태 바에 전면 카메라가 포함되어있는 경우이다.
하지만 상태 바에 전면 카메라가 포함되어있지 않은 경우에는
deviceHeight
에 상태바(status bar)
가 포함되지 않는다.
즉 디바이스 크기 - 네비게이션바
라고 생각하면 된다.
내 휴대폰(갤럭시S21+)은 펀치홀 형식의 전면 카메라를 가지고 있어 카메라가 상태바에 포함된다.
그러나 내가 안드로이드 스튜디오에서 사용하고 있는 에뮬레이터의 경우 전면 카메라가 없으므로 상태바에 전면 카메라가 포함되어있지 않다.
해당 에뮬레이터로 크기를 측정해본 결과는 아래와 같다.
디바이스 크기 : 760
deviceHeight : 712
상태바(status bar) : 24
네비게이션 바(navigation bar) : 48
보다시피 760 - 712 = 48
로 네비게이션 바의 크기만큼을 제외한 수치이다.
다만 전면 카메라가 상태 바에 포함됐을 경우라는 조건은 100% 확실하다고 말하기는 어렵다. 내가 확신하는 나의 추측일뿐이다.