안드로이드 애플리케이션을 개발하면서 제일 신경쓰이는 부분이 모든 디바이스에 최적화 하는 일이다.

UI를 구성할 때 우리는 텍스트, 이미지 등의 크기를 설정하는데 있어 아래와 같은 여러가지 단위를 사용할 수 있다.

px : Pixels
sp : Scaled pixels (scaled to relative pixel size on screen). 
dp : Device independent 
in  : Inches - based on the physical size of the screen.
mm : Millimeters - based on the physical size of the screen.
pt  : Points - 1/72 of an inch based on the physical size of the screen.

px는 화면 위의 점으로 디스플레이의 dpi(dots per inch)가 높아지면 1인치당 들어갈 수 있는 점의 수가 많아져 그림이 작아진다. 
sp는 스케일에 독립적인 화소로서 사용자의 글꼴 크기 설정에 따라서 확대,축소 된다.
dp는 화면의 물리적 밀도에 기반한 추상적인 단위로서 160-di 화면에 상대적이다. 1dp는 160-dpi 화면에서 픽셀 하나의 해당하는 값이다. 

위 내용을 더 설명하자면 dp는 디바이스별로 같은 값을 적용했을 때 실제 적용되는 크기는 동일하게 처리된다.
가령 G1에서 320dip는 320px이고, 넥서스 원에서는 320dip가 480px 이다. 적용되는 픽셀사이즈는 다르지만 크기는 동일하다는 것이다.

sp같은 경우는 같은 디바이스일지라도 실제 픽셀사이즈는 다를 수 있다. 사용자의 선호도에 따라서 크기가 조절될수 있고 이 단위는 주로 텍스트 크기에만 사용된다.

여기서 우리가 얻는 결론은 안드로이드에서 크기 단위를 사용할 때 앞으로 현재 그리고 앞으로 추가될 다양한 디바이스들을 고려한다면 px는 지양하고 dp를 사용할 것을 권장한다는 것이다.


A px --> B dp 변환식 :      B = A * (160/240)

A pt --> B sp 변환식 :       B = A * 11.15/20


px : 화면의 실제 픽셀 (점 하나) 단위
 
in : 실제 화면에서의 1인치 길이
 
mm : 실제 화면에서의 1mm 길이
 
pt : 1/72 인치
 
dp, dip : Density-independent Pixels, 화면 가로 해상도의 1 / 160 (one dp is one pixel on a 160 dpi screen)
 
sp : Scale-independent Pixels, dp와 비슷하지만 화면 해상도 뿐만 아니라 사용자 설정 폰트 크기에도 조절된다. 따라서 폰트에서 사용한다.
 
 
개발하다보면 폰트의 경우는 sp, 나머지는 거의 dp만 사용한다. 
 
그런데 sp나 dp는 xml에서만 의미가 있지 코드상에서는 오직 px만 있다.
 
따라서 코드상에서도 가급적 단위를 변환을 해 줘야 한다.

px = (dp * getContext().getResources().getDisplayMetrics().density + 0.5f);

http://developer.android.com/guide/practices/screens_support.html#dips-pels


여기서 잠깐!! px와 dp에 대해서 먼저 정리하고 넘어가겠습니다.
안드로이드는 160dpi를 기본으로 가정하고 있습니다. 이때 화면 해상도는 320x480이 됩니다.
해상도 320x480에서 가로폭이 160dp가 되기 때문에, 1dp의 크기는 320 / 160 = 2 pixel이라고 볼 수 있습니다.

하지만 요즘 단말기들의 해상도들은 WVGA인 480x800의 단말기가 많습니다.
픽셀 좌표를 이용해서 320x480 단말기에서 GUI를 구성하면 480x800인 단말기에서는 작은 화면으로 출력이 되고,
그 반대로 480x800에서의 GUI를 320x480인 단말기에서 출력하면 GUI가 잘려서 보여지게 됩니다.
심한 경우에는 깨진 GUI를 보이기도 하죠.

이 때를 대비해서 만든 것이 dip(density independent pixel) 단위입니다.
화면의 픽셀 밀도를 정의해서 만든 단위이기 때문에 같은 dip 값을 이용해서 레이아웃을 작성하면 
어느 해상도를 가진 단말기라고 하더라도 같은 비율로 이루어진 GUI 화면을 보여주게 됩니다. 
즉, 화면 해상도에 관계없는 균일한 GUI를 제공하는 어플리케이션을 제공할 수 있는거죠.

안드로이드에서 간주하고 있는 해상도 범주는 크게 3가지 입니다.
LDPI(저해상도), MDPI(중해상도), HDPI(고해상도) 이며, 각각의 밀도값은 LDPI가 120, MDPI가 160, HDPI가 240입니다.
(인치당 픽셀수를 의미합니다.)



그리고 픽셀 좌표와 dip 좌표의 환산공식은 다음과 같습니다.
dip = px * (160 / density)
안드로이드가 160dpi를 기준으로 하고 있기 때문에 위와 같은 공식이 나오는 것이며,


만약 해상도 480x800 단말기에서 이런 수식을 계산하게 된다면, 480x800은 고해상도인 HDPI이기 때문에
480x800 해상도에서 dip와 px 단위 환산
 
dip = px * (160/240) = px * (2/3)
이 됩니다. 따라서 480x800 px 좌표는 320x533 dip 좌표라고 생각하면 됩니다. 

안드로이드 개발을 하다보면 XML은 거의 필수적(?)으로 건드리는 경우가 많습니다.
물론 XML을 사용하지 않고 그냥 java 코드만으로 이루어진 프로젝트들도 많이 있지만,
XML을 사용할 경우 좀 더 간편하고 쉽게 어플리케이션의 레이아웃을 만들 수 있습니다.

개인적으로 가장 좋은 방법은 가중치(weight)를 줘서 화면 크기에 관계없는 레이아웃을 작성하는 것이
가장 좋다고 생각하지만...
[안드로이드] 화면 해상도에 관계없는 레이아웃(Layout) 만들기 - http://snowbora.com/422

가중치를 이용할 경우 XML 코드가 복잡해지고 가독성이 떨어지는 단점이 있습니다.
사실 dp(dip) 단위를 사용해도 다양한 디바이스들의 화면 해상도에 큰 영향을 안 받아야 하지만,
삼성의 갤럭시탭7인치를 비롯해서, 너무 괴상한 해상도의 디바이스들이 많아져서 dp(dip) 단위의
효용성이 많이 줄어들었습니다. 하지만, 그래도 알아두면 나쁠 건 없으니....;;;
한 번 나열해보도록 하겠습니다.


1.px 
픽셀 단위. 화면의 1픽셀을 나타냅니다. 간단한 프로젝트에서는 오히려 사용하기 편할 수도 있습니다.

2. pt
포인트. 일반적으로 폰트 크기에서 사용합니다. 밀리미터나 인치처럼 모바일내가 아닌 바깥에서의 크기 단위입니다.
인치로 환산하면 1/72 인치입니다.

3. dp (dip)
dp라고 하든 dip라고 하든 상관없습니다. 화면의 dpi 크기가 160dpi 일 때, 1 dp는 1 픽셀입니다. 
조금 추상적인 의미라서 사용하기 어렵기도 하고, 정확하지도 않습니다. -_-;;
하지만, 그나마 다양한 해상도를 지원하기 유용한 단위라고 볼 수도 있습니다.

px 단위와의 환산은  dip = px * (160 / density) 입니다.
만약, 480x800 단말기라고 하면, 480x800 단말의 dpi(density)는 240이기 때문에
환산 공식은 dip = px * (160/240) = px * (2/3) 가 됩니다. 

4. sp
스케일과 독립적인 픽셀 크기입니다. dp 처럼 유동적인 크기이며, 주로 폰트 크기 단위로 많이 사용됩니다.

5. in
1 인치를 뜻합니다. 모바일 상에서의 크기가 아닌, 실제 1 인치 크기를 나타냅니다.
좀 애매한 단위겠죠? ^^; 1 인치는 2.54 cm입니다.

6. mm
1 밀리미터를 의미합니다. 


정답은 없지만, 아무래도 그나마 추천드리는 단위는
크기로는 dp, 폰트에는 sp 단위를 쓰는 것이 가장 좋다고 생각합니다.
경우에 따라서는 px 단위까지는 쓸만한 것 같습니다. 

참고 문서 : http://snowbora.com/528


+ Recent posts