Post

[Android] 레이아웃

ViewGroup

  • 다양한 View에 대한 그룹을 관리
  • 계층적 관리 구조를 제공하여 화면 관리의 효율성을 높여줌
  • 각 View 마다 ViewGroup 내부에서 표현되는 구체적인 형태를 지정할 수 있음

layout_width와 layout_height 속성

  • View가 레이아웃에 배치될 때 크기를 결정하는 기준이 됨
  • 서로 독립적으로 동작함
속성값설명
match_parentView가 위치한 레이아웃의 크기에 맞춰 최대한의 크기로 출력
wrap_contentView가 출력한느 내용물의 크기에 맞춰 최소한의 크기로 출력
직접 값(literal)입략한 값에 따라 크기가 결정되어 출력

layout_margin 속성

  • View와 형제 View 사이의 간격을 지정하는 속성
  • View가 레이아웃에 독립적으로 있을 경우 부모 View 사이의 간격으로 설정됨
  • 개별적인 여백을 지정하고 싶다면 layout_marginLeft, layout_marginRight, layout_marginTop, layout_marginBottom 사용

padding과의 차이

  • layout_margin은 View와 부모 또는 형제 View 사이에 적용됨
  • padding은 View와 내용물(그림, 문자 등) 사이에 적용됨
  • layout_margin은 바깥 여백, padding은 안쪽 여백
  • padding은 View 내부에 적용되므로 크기에 포함되지만 layout_margin은 크기에 포함되지 않음
  • padding은 View 자체 속성이지만 layout_margin은 레이아웃 속성
1
2
3
4
5
6
<LinearLayout
  ...
  android:layout_margin="20px"
  android:padding="15dp"
  ...
/>

LinearLayout

  • 내부 구성요소를 선형으로 배치하는 ViewGroup

orientation 속성

  • LinearLayout 내부에 포함된 View들을 배치하는 방향을 지정하는 속성
  • orientation 속성을 별도 지정하지 않으면 기본값으로 horizontal이 적용되어 수평 방향으로 뷰를 배치함
속성값설명
horizontal왼쪽에서 오른쪽으로 수평 방향으로 배열
vertical위에서 아래로 수직 방향으로 배열
1
2
3
4
5
<LinearLayout
  ...
  android:orientation="vertical"
  ...
/>

baselineAligned 속성

  • 수평으로 높이가 다른 TextView를 배치할 때 아래쪽을 기준으로 TextView들을 정렬하는 속성
  • 기본값은 true
1
2
3
4
5
<LinearLayout
  ...
  android:baselineAligned="true"
  ...
/>

gravity 속성

  • View 안쪽에 배치되는 내용물의 정렬 방식을 결정하는 속성
  • 수평/수직 방향을 지정할 수 있으며 | 연산자로 두 속성을 묶어서 지정할 수 있음
    • centercenter_horizontal | center_vertical과 같음
    • center_vertical | right은 수직으로는 중앙, 수평으로는 오른쪽 정렬
  • 각 정렬 방식은 비트 필드(bit field)로 정의되어 있으며, center 속성값과 fill 속성값은 수평/수직 정렬 상태 플래그(flag)의 조합으로 정의됨
  • 기본값은 좌측 상단에 배치됨
속성값설명
center중앙 정렬
left왼쪽 정렬
right오른쪽 정렬
top상단 정렬
bottom하단 정렬
center_vertical수직 중앙 정렬
center_horizontal수평 중앙 정렬
1
2
3
4
5
6
7
8
9
<LinearLayout
  ...
>
  <TextView
    ...
    android:gravity="center"
    ...
  />
</LinearLayout>

layout_weight 속성

  • 상위 레이아웃의 영역에서 내부 레이아웃이나 위젯의 영역 할당 비율을 지정하는 속성
  • 0이면 원래 크기만큼만 영역을 차지하고, 1 이상이면 상위 레이아웃에 포함된 레이아웃이나 위젯들이 layout_weight 값의 크기에 비례하여 상위 레이아웃 영역을 차지하게 됨
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<LinearLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent"
>
  <TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Top Text!!(1)"
    android:layout_weight="1"
    ...
  />
  <TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Top Text!!(3)"
    android:layout_weight="3"
    ...
  />
  <TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Top Text!!(2)"
    android:layout_weight="2"
    ...
  />
</LinearLayout>
  • 위 예제 코드에서 부모 View(LinearLayout)의 전체 높이에 대해 각 TextView가 1:3:2의 비율로 레이아웃 영역을 할당받음
  • layout_weight 속성을 0으로 지정하면 레이아웃 분할에서 제외되고, layout_weight가 0이 아닌 View들이 나머지 영역에 대해 layout_weight 비율로 할당받음
  • layout_height 속성을 0dp로 설정해도 layout_weight 속성에 따라 레이아웃 영역을 할당받아 동일하게 노출됨
  • 부모 View(LinearLayout)의 orientation 속성이 vertical인 경우는 TextView의 layout_width 속성을 wrap_content나 0dp로 설정하면 됨

RelativeLayout

  • ViewGroup에서 View들 사이의 상대적인 관계를 이용하여 View의 위치를 지정하고 배치하는 레이아웃
  • 특정 View와 다른 View 사이의 관계를 지정하려면, 먼저 속성에 다른 View를 지칭하기 위한 식별자(R.java에 등록된 ID)가 필요
  • View의 기본 위치는 부모 레이아웃의 좌측 상단
속성값설명
layout_above지정된 View의 위에 배치
layout_below지정된 View의 아래에 배치
layout_toLeftOf지정된 View의 왼쪽에 배치
layout_toRightOf지정된 View의 오른쪽에 배치
layout_alignLeft지정된 View와 왼쪽 변을 맞춤
layout_alignTop지정된 View와 위쪽 변을 맞춤
layout_alignRight지정된 View와 오른쪽 변을 맞춤
layout_alignBottom지정된 View와 아래쪽 변을 맞춤
layout_alignParentLeft부모와 왼쪽 변을 맞춤
layout_alignParentTop부모와 위쪽 변을 맞춤
layout_alignParentRight부모와 오른쪽 변을 맞춤
layout_alignParentBottom부모와 아래쪽 변을 맞춤
layout_alignBaseline지정된 View와 베이스라인을 맞춤
layout_alignWithParentIfMissinglayout_toLeftOf 등의 속성에 대해 기준이 발견되지 않으면 부모를 기준으로 사용
layout_centerHorizontal부모의 수평 중앙에 배치
layout_centerVertical부모의 수직 중앙에 배치
layout_centerInParent부모의 수평, 수직 중앙에 배치
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<RelativeLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical"
>
  <TextView
    android:id="@+id/target"
    android:layout_centerInParent="true"
    android:text="TARGET"
  />
  <TextView
    android:text="DEFAULT"
  />
  <TextView
    android:layout_above="@id/target"
    android:text="TOP"
  />
  <TextView
    android:layout_below="@id/target"
    android:text="BOTTOM"
  />
  <TextView
    android:layout_toLeftOf="@id/target"
    android:text="LEFT"
  />
  <TextView
    android:layout_toRightOf="@id/target"
    android:text="RIGHT"
  />
</RelativeLayout>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<RelativeLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical"
>
  <TextView
    android:id="@+id/target"
    android:layout_centerInParent="true"
    android:text="TARGET"
  />
  <TextView
    android:text="DEFAULT"
  />
  <TextView
    android:layout_alignTop="@id/target"
    android:text="TOP"
  />
  <TextView
    android:layout_alignBottom="@id/target"
    android:text="BOTTOM"
  />
  <TextView
    android:layout_alignLeft="@id/target"
    android:text="LEFT"
  />
  <TextView
    android:layout_alignRight="@id/target"
    android:text="RIGHT"
  />
</RelativeLayout>

문제점

  • RelativeLayout에서 어떤 View는 상대적인 위치를 결정하기 위해 다른 View에 종속적일 경우가 발생됨
  • 기준이 되는 다른 View가 먼저 정의되어야 종속되는 View의 위치가 결정됨
  • LinearLayout과 달리 사용자의 화면에 보이는 View 순서와 레이아웃 XML 상에 View가 정의된 순서가 다를 수 있음
  • 화면에 출력되는 순서와 무관하게 View 사이의 종속적인 위치만 고려하여 관계를 정의하다 보면, 대체되는 배치를 찾기 어렵거나 유지보수에 어려움이 발생할 수 있음
  • 기준이 되는 View가 삭제되거나 위치를 이동하면, 종속되는 View는 원하는 위치를 결정하지 못하게 됨

AbsoluteLayout

  • 절대적인 위치 지정이 가능한 레이아웃으로 RelativeLayout의 반대 속성을 가지는 레이아웃
  • 관계나 순서에 상관없이 지정한 절대 좌표에 View를 배치함
  • layout_x, layout_y 속성을 지정하면 부모의 좌측 상단(0,0)을 기준으로 하는 좌표에 View가 배치됨
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<AbsoluteLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent"
>
  <TextView
    android:layout_x="50dip"
    android:layout_y="350dip"
    android:text="Absolute(50, 350)"
  />
  <TextView
    android:layout_x="130dip"
    android:layout_y="90dip"
    android:text="Absolute(130, 90)"
  />
</AbsoluteLayout>

FrameLayout

  • 모든 자식 View가 FrameLayout의 좌측 상단에 나타나는 레이아웃
  • 자식 View가 두 개 이상일 때는 추가된 순서대로 겹쳐서 표시
  • XML 코드에 먼저 정의된 자식 View가 아래에 위치하고 나중에 추가된 자식 View가 위에 겹쳐서 출력됨
속성값설명
foreground자식 View의 위쪽에 살짝 얹히는 이미지를 지정함
foregroundGravityforeground 이미지의 위치를 결정함
measureAllChildren레이아웃 크기를 모든 자식 View의 크기에 맞출 것인지, visibility 속성이 visible로 설정된 자식 View에만 맞출 것인지를 결정함
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<FrameLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent"
>
  <TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:src="@drawable/banana"
  />
  <TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:src="@drawable/earth"
  />
</FrameLayout>

TableLayout

  • 표 형태로서 자식 View를 배치하는 레이아웃
  • TableRow 객체 하나가 하나의 행에 해당됨
    • 여러 개의 행이 하나의 TableLayout에 배치되려면 적응적으로 세로의 크기가 조정되어야 함
    • 이에 따라 TableRow의 높이는 wrap_content로 설정해야 함
  • TableRow 내부는 여러 개의 열(셀)로 구성되며 하나의 열에는 하나의 자식 View가 포함됨
    • 하나의 셀에 배치되는 자식 View는 무조건 주어진 셀 안에 배치되므로 layout_width 속성은 wrap_content를 기본값으로 가짐
    • 자식 View의 높이는 기본 속성값으로 wrap_content로 설정되지만, 필요한 경우 match_parent로 지정하여 하나의 셀로 행을 채울 수도 있음
  • TableRow의 개수가 행의 개수이고 하나의 TableRow 안에 배치되는 자식 View의 개수가 열(셀)의 개수이므로 TableLayout의 전체 크기는 행X열로 계산됨
  • 가로 행과 세로 열의 개수에는 특별한 제한이 없음

속성값설명
shrinkColumns콤마로 구분된 열 인덱스 목록. TableLayout의 전체 너비가 화면보다 클 때, 지정된 열을 축소시켜 화면에 맞춤
stretchColumns콤마로 구분된 열 인덱스 목록. TableLayout의 너비가 화면보다 작을 때, 지정된 열을 확장시켜 화면에 맞춤
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<TableLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent"
>
  <TableRow>
    <TextView
      android:text="SUN"
    />
    <TextView
      android:text="MON"
    />
    <TextView
      android:text="TUE"
    />
  </TableRow>
</TableLayout>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<TableLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:stretchColumns="1"
>
  <TableRow>
    <TextView
      android:text="SUN"
    />
    <TextView
      android:text="MON"
    />
    <TextView
      android:text="TUE"
    />
  </TableRow>
</TableLayout>

레이아웃 중첩

  • 레이아웃은 View들을 담는 하나의 컨테이너(쟁반)이므로 View로부터 파생된 모든 ViewGroup과 View를 레이아웃 안에 포함할 수 있음
  • 레이아웃 내에 포함되는 ViewGroup에 다른 View들을 중첩하여 배치할 수 있음
  • 레이아웃 자체도 View의 파생 클래스이므로 레이아웃끼리 중첩하여 배치 가능
  • 레이아웃 중첩은 화면 디자인의 유지보수를 쉽게 하고 XML 코드의 가독성을 향상시킴
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<LinearLayout>
  <TextView />
  <TableLayout>
    <TableRow>
      <TextView/>
      <TextView/>
      <TextView/>
    </TableRow>
    <TableRow>
      <TextView/>
      <TextView/>
      <TextView/>
    </TableRow>
  </TableLayout>
  <LinearLayout>
    <TextView />
    <TextView />
    <TextView />
  </LinearLayout>
</LinearLayout>

This post is licensed under CC BY 4.0 by the author.