안드로이드 폰은 크기가 다양해서 개발자에게는 크기가 다양한 기기와 호환하는 화면을 만드는 것이 중요한 과제이다.
폰 크기와 호환성은 안드로이드 시스템에서 도와주는 부분이 있고 개발자가 직접 코드에서 해결해야 하는 부분이 있다. 우선 안드로이드 시스템에서는 기기의 크기를 어떻게 판단하는지 살펴보자.
논리적인 단위 알아보기
안드로이드 시스템은 기기의 크기를 ldpi, mdpi, hdpi, xhdpi, xxhpi, xxxhdpi로 구분한다. 여기서 dpi는 dots per inch의 줄임말로 1인치 안에 있는 도트의 개수를 의미한다.
안드로이드 시스템은 기기의 크기를 구분하여 콘텐츠의 크기를 늘리거나 줄여서 그에 맞게 나올 수 있도록 돕는다. 그런데 그러려면 개발자가 콘텐츠의 크기를 지정할 때 논리적인 단위를 사용해야 한다. 물리적인 단위로 지정하면 시스템의 도움을 받을 수 없다.
안드로이드에서 앱을 개발할 때 크기 지정에 사용할 수 있는 단위는 다음과 같다.
- dp(dip: density-independent pixels): 스크린의 물리적 밀도에 기반을 둔 단위
- sp(sip: scale-independent pixels): dp와 유사하며 글꼴 크기에 적용
- pt(points): 스크린 크기의 1/72을 1pt로 함
- px: 픽셀
- mm: 밀리미터
- in: 인치
안드로이드에서는 논리적인 단위인 dp와 sp로 크기를 지정하길 권한다. dp는 일반 크기, sp는 글꼴 크기를 의미한다. 물리적인 px와 논리적인 dp 단위로 크기를 지정하는 예를 비교해보자.
// px와 dp 단위 크기 지정 예
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="HelloWorld"
android:textSize="12px" /> // px단위로 글자 크기 지정함
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="HelloWorld"
android:textSize="12dp" /> // dp단위로 글자 크기 지정함
앱을 xxxhdpi 크기의 폰으로 실행했을 때, 단위를 px로 설정한 뷰의 문자열은 너무 작게 나온다. 단위를 dp로 설정하면 시스템에서 기기의 dpi를 보고 크기를 조정하여 출력하므로 문자열이 px 단위를 사용할 때보다 크게 출력된다.
안드로이드 시스템은 mdpi 폰을 기준으로 크기를 조정하며 mdpi 폰에서 1dp는 1px 이다. 즉, 10dp로 지정하면 화면에 10px로 출력해준다. 기기별로 배율이 있다. xxhdpi 폰은 배율이 3.0이라서 개발자가 지정한 크기보다 3배정도 크게 출력해준다. 결국 콘텐츠의 크기를 지정할 때는 될 수 있으면 논리적인 단위로 지정하여 시스템의 도움을 받아 기기의 크기에 맞게 나오도록 처리해야 한다.
❓화면에 3배 크게 나오면 문제 아닌가요?
❗️화면에 나오는 길이가 3.0배가 된다는 게 아니라 출력할 때 차지하는 픽셀 수가 3.0배라는 의미이다. xxhdpi 폰은 같은 물리적 크기의 mdpi 폰의 3배 픽셀수를 가지기 때문에 밀도가 더 높다. 따라서 3배정도 많은 픽셀수를 차지하게 해야 눈으로 봤을 때 비슷해진다.
화면 정보 가져오기
안드로이드 시스템은 기본적으로 호환성을 지원하지만 때로는 개발자가 직접 코드에서 조정할 수도 있다. 이때 기기의 크기 정보를 가져오는 방법은 API 레벨 30 버전과 이전 버전에서 차이가 있다. 30 이전 버전에서는 DisplayMetrics로 크기 정보를 가져왔지만 30 버전부터는 이 방법을 지원하지 않고 (deprecation)(??), WindowMetrics를 이용해야 한다. 따라서 다음처럼 30버전을 기준으로 버전을 구분해서 작성해야 한다.
다음 코드는 기기의 가로, 세로 크기를 가져오는 코드이다.
// 기기의 가로, 세로 크기 가져오기
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val windowMetrics: WindowMetrics = windowManager.currentWindowMetrics
binding.textView.text = "width : ${windowMetrics.bounds.width()},
height : ${windowMetrics.bounds.height()}"
} else {
val display = windowManager.defaultDisplay
val displayMetrics = DisplayMetrics()
display?.getRealMetrics(displayMetrics)
binding.textView.text = "width : ${displayMetrics.widthPixels},
height : ${displayMetrics.heightPixels}"}
실행결과 예시:
width : 1080, height : 1920
Build.VERSION.SDK_INT는 앱이 실행되는 기기의 버전값이며 Build.VERSIO_CODES.R은 안드로이드 11 버전, 즉 API 레벨 30을 의미한다.
'깡샘 코틀린' 카테고리의 다른 글
10-2 퍼미션 설정하기 (0) | 2023.06.24 |
---|---|
10-1 API 레벨 호환성 고려하기 (2) | 2023.06.24 |
09-2 리소스 조건 설정 (0) | 2023.06.23 |
09-1 리소스의 종류와 특징 (0) | 2023.06.23 |
08-2 뷰 이벤트 (0) | 2023.06.23 |