안드로이드 레이아웃 공통사항. (Android Layout Common)
1. "layout_"으로 시작하는 속성.
Layout에 여러 View 위젯들을 사용하는 예제들을 살펴보면, 많은 속성들 중에 "layout_"으로 시작하는 속성들이 있는 것을 볼 수 있습니다. View가 부모 Layout에서 차지하는 영역의 크기를 지정하는데 사용되는 "layout_width"와 "layout_height", View와 부모 Layout 사이의 여백을 설정하기 위한 "layout_margin", 그리고 부모 Layout 내에서 View가 정렬되는 위치를 결정하기 위한 "layout_gravity" 등이 바로 "layout_"으로 시작하는 속성들이죠.
그런데 "layout_"으로 시작하는 속성들의 특징을 살펴보면 한 가지 공통점이 있는 것을 발견할 수 있습니다. 바로, "layout_" 속성이, View(또는 ViewGroup)가 자신의 배치 관련 설정을 부모 Layout에게 요청하는 역할을 한다는 것입니다. 즉, View에 사용되는 대부분의 속성들이 View 자체의 형태를 위한 속성이라면, "layout_"으로 시작하는 속성은 부모 Layout 내부에서 View가 가지는 크기, 여백, 위치 등을 설정하기 위한 속성인 것입니다.
하지만 "layout_"으로 시작하는 속성들을 사용한다고 해서, 그 속성 값이 View의 배치에 그대로 적용되는 것은 아닙니다. Layout 내에 있는 다른 View 위젯들의 속성 값 및 관계가 먼저 고려된 다음, 가능하다면 View 위젯의 속성 값이 최대한 반영되는 것이죠.
그럼 지금부터 "layout_"으로 시작되는 속성들에 대해 살펴보겠습니다.
2. Layout 또는 자식(Children) View 위젯에 적용될 수 있는 공통 속성
[안드로이드 레이아웃]에서 살펴봤듯이, Layout 클래스는 표시 형태 및 사용 용도에 따라 여러 종류가 존재합니다. 그리고 각 Layout의 용도에 맞게 다양한 속성이 제공되고 있죠. 하지만 화면에 차지하는 영역 크기, 여백, 정렬 등은 모든 Layout 및 자식(Children) View 위젯에 공통적으로 적용될 수 있는 속성입니다.
2.1 Layout 또는 View 위젯의 크기. (layout_width, layout_height)
Layout 또는 자식(Children) View 위젯을 사용할 때는 너비와 높이를 지정해야 합니다. 너비는 "layout_width" 속성을 사용하고, 높이는 "layout_height" 속성을 사용하여 지정합니다. layout_width 및 layout_height 속성에 크기를 지정할 때 100dp, 200px 등의 고정된 치수 값을 사용할 수 있지만, 일반적으로 고정 값 사용은 권장되지 않습니다. (만약 고정 값 사용이 필요하다면 dp 단위를 사용하시길 권장합니다.)
대신, "match_parent" 또는 "wrap_content" 중 하나의 값을 사용하는 것이 적당한 경우가 많습니다. match_parent는 Layout 또는 View 위젯을 상위 Layout이 허용하는 최대 크기에 맞게 늘릴 때 사용되는 값이며, wrap_content는 Layout 또는 View 위젯이 가진 내용에 맞는 크기를 갖게 하고자 할 때 사용되는 값입니다.
만약 Layout(검은 실선 영역)과 자식 View 위젯이 둘 다 wrap_content라면 아래와 같이 표시될 것입니다.
Layout과 자식 View 위젯이 모두 match_parent라면 아래와 같이 표시됩니다.
다음은 Layout이 match_parent이고, 자식 View 위젯이 wrap_content인 경우입니다.
마지막으로 Layout이 wrap_content이고 자식 View 위젯이 match_parent인 경우, 둘 다 wrap_content인 경우와 동일한 출력 결과가 표시됩니다. 하지만 표시 결과가 어떤 식으로든 나온다고 하더라도, 상호 참조가 이루어지거나 기준이 모호한 정의는 피하는 것이 좋습니다.
2.2 Layout 또는 자식(Children) View 위젯 요소 간 여백. (layout_margin, padding)
Layout에 자식 View 위젯들이 표시될 때, Layout과 View 위젯 사이 또는 인접한 두개의 View 위젯 사이에 여백을 위한 공간이 존재하지 않으면, 앱이 보여주고자 하는 내용의 가독성과 사용 편의성이 현저히 떨어지게 됩니다. 반대로 여백이 너무 많아도 유사한 문제가 발생하죠.
이처럼 Layout과 View 위젯을 화면에 배치할 때는 각 요소 사이에 적절한 여백이 주어져야 하며, 안드로이드에서 여백으로 사용되는 속성에는 Margin과 Padding이 있습니다.
Margin은 View 위젯과 상위 Layout 사이에 주어지는 공간을 의미하며, View 위젯의 영역에 포함되지 않습니다. 반면 Padding은 View 위젯의 실제 내용(텍스트, 이미지 등)과 View 위젯 경계 사이의 추가적인 공간을 말합니다. View 위젯 영역에 포함되는 공간이죠.
View 위젯에 Margin과 Padding을 적용하기 위해서는 각각 "layout_margin"과 "padding" 속성을 사용합니다.
아래는 layout_margin과 padding 속성에 "30dp"를 사용한 예제입니다.
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FFFFFF">
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_margin="30dp"
android:padding="30dp"
android:background="#AAAAAA"
android:src="@drawable/android_logo" />
</LinearLayout>
그리고 Margin과 Padding을 설정할 때, 상,하,좌,우 방향에 대해 개별적인 값을 사용할 수 있습니다. Margin을 각 방향에 대해 설정할 때는 "layout_marginTop", "layout_marginBottom", "layout_marginLeft", "layout_marginRight" 속성을 사용하고, Padding의 경우에는 "paddingTop", "paddingBottom", "paddingLeft", "paddingRight"로 나누어 사용합니다.
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FFFFFF">
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="20dp"
android:layout_marginRight="30dp"
android:layout_marginBottom="40dp"
android:paddingLeft="10dp"
android:paddingTop="20dp"
android:paddingRight="30dp"
android:paddingBottom="40dp"
android:background="#AAAAAA"
android:src="@drawable/android_logo" />
</LinearLayout>
2.3 Layout 내의 View 위젯의 위치 정렬. (layout_gravity)
Layout에 자식 View 위젯이 배치되면, 기본적으로 좌측 상단에 표시됩니다. 즉, Layout에 위치 정렬과 관련된 어떠한 속성도 사용되지 않은 경우, 기본적인 정렬 방향이 수평(horizontal) 방향으로 왼쪽에, 수직(vertical) 방향으로 위쪽이 된다는 것이죠.
"layout_gravity" 속성을 사용하면, Layout 내에서 자식 View 위젯이 정렬되는 위치를 바꿀 수 있습니다.
* android:layout_gravity - 자신이 속한 부모 Layout내 자신의 정렬 위치 값 지정.
> 부모 Layout 내에서 x축(좌/우)과 y축(상/하)을 기준으로 정렬.
> 아래 값들 중에서 하나 이상의 값을 '|' 기호로 혼합하여 사용.
-. top (0x30) : 부모 Layout 안에서, 위쪽에 위치.
-. bottom (0x50) : 부모 Layout 안에서, 아래쪽에 위치.
-. left (0x03) : 부모 Layout 안에서, 왼쪽에 위치.
-. right (0x05) : 부모 Layout 안에서, 오른쪽에 위치.
-. center_vertical (0x10) : 세로 기준으로 가운데 위치.
-. fill_vertical (0x70) : 세로 방향으로 가득 채움.
-. center_horizontal (0x01) : 가로 기준으로 가운데 위치.
-. fill_horizontal (0x07) : 가로 방향으로 가득 채움.
-. center (0x11) : 가로, 세로 기준으로 가운데 정렬.
-. fill (0x77) : 가로, 세로 방향으로 가득 채움.
-. clip_vertical (0x80) : 세로 기준으로 Layout을 넘어서는 영역 자르기.
-. clip_horizontal (0x08) : 가로 기준으로 Layout를 넘어서는 영역 자르기.
-. start (0x00800003) : 부모 Layout 안에서, 시작 위치에 정렬.
-. end (0x00800005) : 부모 Layout 안에서, 끝 위치에 정렬.
> 부모 Layout이 RelativeLayout인 경우, 적용되지 않음.
아래는 LinearLayout에서 자식(Children) TextView의 layout_gravity 속성에 각각 "left", "right", "center_horizontal", "fill_horizontal", "clip_horizontal", "start", "end" 값을 사용한 결과입니다. 즉, 가로(horizontal) 방향 정렬과 관련된 값을 적용한 예제입니다.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF0000"
android:textSize="20sp"
android:layout_gravity="left"
android:text="left" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00FF00"
android:textSize="20sp"
android:layout_gravity="right"
android:text="right" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#0000FF"
android:textColor="#FFFFFF"
android:textSize="20sp"
android:layout_gravity="center_horizontal"
android:text="center_horizontal" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FFFF00"
android:textSize="20sp"
android:layout_gravity="fill_horizontal"
android:text="fill_horizontal" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF00FF"
android:textSize="20sp"
android:layout_gravity="clip_horizontal"
android:text="clip_horizontal" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00FFFF"
android:textSize="20sp"
android:layout_gravity="start"
android:text="start" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#000000"
android:textColor="#FFFFFF"
android:textSize="20sp"
android:layout_gravity="end"
android:text="end" />
</LinearLayout>
다음은 layout_gravity 속성에 각각 "top", "bottom", "center_vertical", "fill_vertical", "clip_vertical" 값을 사용한 결과입니다. 즉, 세로(vertical) 방향 정렬과 관련된 값을 적용한 예제입니다.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF0000"
android:textSize="20sp"
android:layout_gravity="top"
android:text="top" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00FF00"
android:textSize="20sp"
android:layout_gravity="bottom"
android:text="bottom" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#0000FF"
android:textColor="#FFFFFF"
android:textSize="20sp"
android:layout_gravity="center_vertical"
android:text="center_vertical" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FFFF00"
android:textSize="20sp"
android:layout_gravity="fill_vertical"
android:text="fill_vertical" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF00FF"
android:textSize="20sp"
android:layout_gravity="clip_vertical"
android:text="clip_vertical" />
</LinearLayout>
아래 예제는 layout_gravity 속성에 "center" 값을 지정한 결과입니다. "center" 속성은 가로(horizontal), 세로(vertical) 방향을 기준으로 가운데 정렬을 위한 속성이므로 "center_horizontal|center_vertical"을 지정한 것과 같은 결과를 표시합니다. 또한 아래 예제에서는 정확한 결과 확인을 위해 LinearLayout 대신 FrameLayout을 사용하였습니다.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#000000"
android:textColor="#FFFFFF"
android:textSize="20sp"
android:layout_gravity="center"
android:text="center" />
</FrameLayout>
2.3.1 "layout_gravity" 속성과 "gravity" 속성
Layout 요소에 사용할 수 있는 정렬 관련 속성은 "layout_gravity"와 "gravity", 두 가지가 있습니다. 이름이 비슷하여 사용 방법이 혼동될 수 있지만, 이 글의 초반에 간단히 언급했던 "layout_"으로 시작하는 속성의 특징을 되짚어보면, 쉽게 구분할 수 있을 것입니다.
"layout_gravity" 속성은 앞서 설명한대로, 부모 Layout 내에서 View가 정렬되는 위치를 결정하는 속성입니다. 반면, "gravity" 속성은 부모 Layout과는 관계없이, View 위젯 내에 표시되는 내용이 정렬되는 위치를 정하기 위한 속성입니다. 즉, TextView를 예로 들자면, TextView 위젯 안에 표시되는 텍스트가 TextView 내에서 어디에 정렬될 것인가를 지정하기 위한 속성이 바로 "gravity" 속성인 것입니다.
아래는 layout_gravity와 gravity 속성을 사용하여 TextView와 텍스트의 정렬 결과를 확인할 수 있는 예제 소스 코드입니다. 차이점 구분을 보다 명확하게 확인하기 위해, 각 요소의 크기(width, height) 값에 고정 크기를 지정한 것을 주의하세요.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#00FF00">
<TextView
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#0000FF"
android:textColor="#FFFFFF"
android:layout_gravity="center"
android:gravity="left|center_vertical"
android:text="TEXT"/>
</FrameLayout>
2.3.2 Layout의 "gravity" 속성과 자식(Children) View 위젯의 "layout_gravity" 속성의 충돌.
앞서 설명한대로 gravity 속성은 자신이 표현하는 내용의 정렬 기준을 설정하기 위한 속성입니다. 반면 layout_gravity 속성은 부모 Layout 내에서 자신의 정렬 기준을 요청하기 위한 속성이죠.
그럼 만약, 부모 Layout에서 gravity 속성에 "right" 값을 지정하여 자식(Children) View 위젯을 오른쪽에 정렬하려고 하고, 자식(Children) View 위젯에서는 layout_gravity 속성에 "left" 값을 지정하여 왼쪽에 정렬되려고 하면 어떤 결과가 나오게 될까요?
예제 코드를 통해, 결과를 직접 확인해보죠.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="right">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF0000"
android:textSize="30sp"
android:text="none" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00FF00"
android:textSize="30sp"
android:layout_gravity="left"
android:text="left" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#0000FF"
android:textColor="#FFFFFF"
android:textSize="30sp"
android:layout_gravity="center"
android:text="center" />
</LinearLayout>
표시되는 결과를 보면, 부모 Layout의 gravity 속성이 아닌, 자식 View 위젯의 layout_gravity 속성이 적용되는 것을 확인할 수 있습니다. 하지만 layout_gravity를 사용하지 않은 "none" TextView의 경우, 부모 Layout의 gravity 속성을 따릅니다.
결과적으로 부모의 gravity 속성이 먼저 적용된 다음, 자식의 layout_gravity가 적용되어 정렬 결과를 덮어쓰게 되는 것입니다.
3. 참고.
- 안드로이드 레이아웃에 대한 개요.
- [안드로이드 레이아웃]을 참고하세요.
- ViewGroup에 대한 자세한 도움말.
- [안드로이드 개발 참조문서 ViewGroup 항목]을 참고하세요.
- 레이아웃에 대한 자세한 도움말.
- [안드로이드 개발 API 가이드 레이아웃 항목]을 참고하세요.
- LinearLayout에 대한 자세한 도움말.
- [안드로이드 개발 API 가이드 LinearLayout]을 참고하세요.
- [안드로이드 개발 참조문서 LinearLayout]을 참고하세요.
- RelativeLayout에 대한 자세한 도움말.
- [안드로이드 개발 API 가이드 RelativeLayout]을 참고하세요.
- [안드로이드 개발 참조문서 RelativeLayout]을 참고하세요.
- TableLayout에 대한 자세한 도움말.
- [안드로이드 개발 참조문서 TableLayout]을 참고하세요.
- FrameLayout에 대한 자세한 도움말.
- [안드로이드 개발 참조문서 FrameLayout]을 참고하세요.
.END.