android 기기 해상도에 따른 이미지 크기 설정하기

2020. 8. 30. 15:10android

1. android dpi


안드로이드는 해상도 기준이 존재합니다. 먼저 android에서 기준이 되는 사이즈는 mdpi입니다. 이 mdpi를 기준으로 px과 dp 값을 계산할 수 있으며 실제로 디자이너들이 가장 많이 작업하는 사이즈는 mdpi를 기준으로 많이 작업하기 때문에 알아두면 미래 디자이너와 이야기 소통이 조금 원만하게 이뤄질 수 있겠지요?

 

그림에서 볼 수 있듯이 dpi기준을 일정 범위로 하는 것을 볼 수 있습니다. 이는 왜그럴까요?

 

이유는 모바일 기기의 해상도가 항상 정직한 크기로 나오지 않기 때문입니다. 위의 그림에서 보여지듯이 기준이 되는 사이즈는 120, 160, 240, 320, 480, 640dpi이지만 실제 모바일의 사이즈는 해당 dpi 기준의 범위에 속하는 형태입니다. 한 마디로 500dpi, 360dpi 이렇게 말이죠. 그렇기 때문에 모바일 기기마다 해상도를 확인하고 해당 기기만을 위한 dpi를 관리할 필요없이 대표가 되는 사이즈만 관리하면 됩니다. 

2. dp란?


dp는 android 화면을 구성하는 view들의 크기를 지정할 때 주로 사용이 되는 단위입니다. 그럼 왜 dp를 사용할까요? 

그 이유는 어느 해상도이든지 간에 동일한 뷰를 보여주고 싶기 때문이죠. 만약 단위를 dp를 사용하지 않고 px을 사용한다면 dpi별로 뷰의 크기가 천차만별일 것입니다. 왜냐하면 화면을 구성하는 최소 단위가 px이므로 기기가 갖는 pixel 수에 따라서 50 x 50 pixel 사이즈를 갖는 뷰는 크게 보일수도 작게 보일 수도 있기 때문입니다.

 

이를 해결하기 위해서 dp가 나오게 되었고 mdpi를 기준으로 해상도별로 동일한 크기의 이미지를 갖도록 하기 위해서 내부적으로 계산이 이뤄지게 됩니다. 그리고 해상도별로 동일한 사이즈의 이미지를 갖도록 해줍니다!

3. 해상도에 따른 이미지 관리하기


해상도에 따라서 이미지를 관리하기 위해서는 먼저 이미지를 어디서 얻어오는지 구분을 지을 필요가 있습니다. 조금 더 풀어서 설명하자면 서버로부터 받아오는 고정 이미지를 다뤄야 하거나, dpi별로 이미지를 나눌 수 있는 상황인지로 구분 지을 수 있습니다. 

 

이미지의 기준을 정하면 이제부터 해상도별로 관리가 들어가야합니다. 

 

1)서버로부터 얻어오는 이미지

- 서버로부터 얻어오는 이미지는 말 그대로 서버에 이미지가 저장되어져 있습니다. 그런데 서버가 기기마다 해상도를 파악해서 해상도에 맞는 사이즈로 이미지를 줄 수 있을까요?

할 수는 있겠지만 이는 클라이언트에서 자신의 기기 해상도를 파악해서 서버에게 알려주는 API가 있어야 할 뿐더러, 서버로부터 이미지를 많이 받아오는 앱이라면... 서버가 해상도별로 이미지를 전부 갖고 있는 것 또한 매우 비효율적일 것입니다. 그래서 기본적으로 서버는 고정 이미지를 갖습니다. 그러고 클라이언트에게 고정 이미지를 던져주고 알아서 핸들링하도록 지향하고 있습니다. 이를 처리하기 위해서는 안스 IDE에서는 values 폴더에 dimens.xml를 통해서 핸들링 할 수 있도록 해주고 있습니다. 즉 해상도별로 고정 이미지의 사이즈를 dimens 폴더를 해상도별로 나눠서 관리해 줘야합니다.

 

2) 기본적으로 갖고있는 이미지

- 서버로부터 얻어오지 않고 기본적으로 사용되는 이미지들은(버튼 이미지, 검색 bar...etc) 기본적으로 해상도 별로 나눠서 갖고 있어야합니다. 즉 동적으로 이미지를 얻어오는 것이 아니라 이미 갖고 있는 것이죠. 때문에 사용자들이 app을 다운로드 할 때 해상도별로 나눠진 이미지들을 함께 다운로드하도록 폴더에 미리 이미지들을 넣습니다. 이렇게 기본적으로 가지고 있어야하는 이미지는 minmap 폴더를 dpi별로 나눠서 이미지를 저장하고 있으면 됩니다. 

4. 고정 이미지의 사이즈 dpi별로 나누기


먼저 2가지 방법 중 1번째 방법입니다. 서버로부터 이미지를 받아오면 이는 고정 이미지이기 때문에 해상도별로 dp값을 나눠서 관리해줘야 합니다. 그래야 각 기기가 app 실행 시, 자신의 해상도에 맞는 이미지 크기를 참조하기 때문입니다. (만약 해상도 별로 dp를 관리해주지 않으면 wrap_parent, match_parent 또는 직접 입력한 dp값으로 이미지가 지정됩니다.)

 

root tree를 [android] -> [project]로 변경하여 관리되는 폴더의 기준을 변경합니다. 여기서 해상도별로 나눠줄 폴더는 바로 values입니다.

 

이유는 values는 색, 스트링, 크기 등을 관리해주는 폴더이기 때문입니다. (해상도별로 사이즈가 다른 이미지를 넣어줘야 하니까 values와 연관된 작업이란 걸 알 수 있죠?)

 

values 폴더에서 크기를 다룰 것이기 때문에 각 해상도별로 values는 dimens를 갖도록 만듭니다.

 

이렇게 values 폴더를 해상도별로 각각 만들어 준 다음 각 폴더에 dimens.xml을 또 생성해 줍니다. 

 

그리고 각 해상도에 맞는 사이즈로 dp값을 dimens에 적어주시면 됩니다. 

 

 

 

dimens 내부의 구조입니다. 왼쪽 사진에서는 values-hdpi폴더의 dimens입니다. 이렇게 나머지 values 폴더의 dimens도 dp값을 지정해 주면 됩니다. 한 이미지 크기를 지정하기 위한 name이 launcher_size였으면 나머지 values 폴더에서도 모두 동일한 name을 갖도록해야합니다. 그래야 기기가 자신의 해상도에 따른 values 폴더를 참조할 때 옳바른 값을 찾을 수 있습니다.

 

dimens 내부에서 사용할 dp값을 name과 value를 지정하면 xml에서 width, height로 사용할 수 있습니다. 

 

저는 launcher_size를 50dp로 설정했기 때문에 xml에서는 크기를 launcher_size를 통해서 지정할 수 있습니다. 

 

 

dimens에서 만든 크기를 사용하는 방법입니다. 이렇게 이미지의 가로, 세로 넓이를 launcher_size로 지정해 놓으면 자동으로 기기가 자신의 해상도에 따른 values를 참조하게 되므로 각 해상도별로 사이즈를 핸들링할 수 있게 됩니다.

 

예를들어 xxhdpi에 launcher_size를 =120dp로 했다면 xxhdpi를 같은 모바일 기기에서는 해당 이미지를 120 x 120 dp 사이즈로 변경하여 보여지게 됩니다.

5. 이미지 dpi별로 나누기


이번에는 2가지 방법 중 2번째 방법입니다.

 

리소스를 관리하는 root tree의 기준을 [android]-> [project]로 변경해 줍니다. 그러면 왼쪽의 사진처럼 dpi별로 minmap이 구분되어져 있는 구조를 볼 수 있습니다.

 

각 해상도별로 나눠진 minmap에 해상도별로 이미지를 넣어주셔야합니다. 쉽게 말해서 minmap-hdpi 폴더에는 hdpi사이즈의 이미지가 들어가야합니다.  

 

이렇게 기본적으로 갖고있어야 하는 이미지들은 해상도 별로 나눠서 갖고있으면 됩니다. 

 

이때 가장 중요한 점은 이미지의 name은 해상도별로 모두 동일해야합니다! 그래야 xml에서 src="이미지 name"을 참조할 때 문제 없이 해상도에 따른 이미지가 적용됩니다.

 

6. 정리


가장 중요한 것은 이미지를 해상도별로 갖을 수 있는 상황인지, 아니면 서버에서 받는 이미지처럼 고정이미지를 다뤄야하는 지가 중요합니다. (추가적으로 text의 사이즈도 values의 dimens에서 관리가 되어질 수 있습니다.)

 

두가지 상황이 혼재된다 하더라도 구분만 잘 지으면 해상도가 다른 기기라 할지라도 동일한 화면을 보여줄 수 있을 것입니다. 

'android' 카테고리의 다른 글

Observer pattern 구조 및 사용  (0) 2020.12.27
SINGLE_TOP, CLEAR_TOP,NEW_TASK로 액티비티 task 관리하기  (0) 2020.12.13
android ConstrainLayout  (2) 2020.08.24
room과 Rxjava2 같이 사용하기  (7) 2020.08.21
ViewModel 사용하기  (4) 2020.08.19