본문 바로가기

유저 인터페이스/레이아웃(Layout)

네 자리는 내가 결정한다 - 레이아웃(Layout)

안드로이드의 화면을 구성하는 요소는 크게 레이아웃(Layout)과 위젯(Widget)으로 나눌 수 있습니다. 

위젯은 텍트스를 표시해주는 TextView, 그림을 표시해주는 ImageView, 버튼, EditText, RadioButton, CheckBox 등 사용자의 입력을 받거나 화면에 데이터를 표시해주는 것들이며, 레이아웃은 이러한 위젯들을 어떠한 방식으로 화면에 배치해줄지를 결정해주는 하나의 "컨테이너" 역할을 합니다.

레이아웃에 포함되는 위젯들은 하나의 뷰(View)를 상속받은 것들이며, 결국 레이아웃은 뷰들을 담을 수 있는 객체라 할 수 있습니다. 따라서, 레이아웃을 ViewGroup이라고도 합니다. (실제로 다른 뷰를 담을 수 있는 객체들은 ViewGroup을 상속하고 있습니다.)

일반적인 윈도우 어플리케이션 등에서 레이아웃을 짤 때는 주로 각각의 구성요소를 마우스로 끌어서 원하는 위치에 놓는 방식으로 화면을 구성하는데, 안드로이드는 자바의 Swing어플리케이션의 레이아웃을 짤 때 처럼 절대적인 위치를 지정하기 보다는 일정한 규칙에 의해서 각각의 구성요소를 배치하는 방식을 주로 사용합니다. (물론, 절대적인 위치를 지정하는 레이아웃도 있기는 하다만, 자주 쓰이지는 않습니다)

자, 그럼 슬슬 안드로이드의 레이아웃에 대해 하나씩 알아보도록 하겠습니다.

1. LinearLayout

가장 기본적이면서도 가장 많이 사용되는 레이아웃입니다. 레이아웃 내의 요소들을 수직, 수평으로 배치합니다.
배치 방향을 결정하는 속성은 orientation으로, vertical로 설정시 레이아웃 내의 요소들을 수직으로, horizontal로 설정시 수평으로 배치하게 됩니다.

orientation="vertical" 일 경우
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />
<EditText android:text="EditText" 
	android:id="@+id/EditText01" 
	android:layout_width="wrap_content" 
	android:layout_height="wrap_content"/>

<Button android:text="Button" 
	android:id="@+id/Button01" 
	android:layout_width="wrap_content" 
	android:layout_height="wrap_content"/>
	
</LinearLayout>

수직 방향으로 요소들이 배치된 모습



orientation="horizontal" 일 경우
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />
<EditText android:text="EditText" 
	android:id="@+id/EditText01" 
	android:layout_width="wrap_content" 
	android:layout_height="wrap_content"/>

<Button android:text="Button" 
	android:id="@+id/Button01" 
	android:layout_width="wrap_content" 
	android:layout_height="wrap_content"/>
	
</LinearLayout>

수평 방향으로 요소들이 배치된 모습




2. RelativeLayout

RelativeLayout은 레이아웃 내의 요소들간에 위치관계를 부여하고, 그 관계에 따라 화면을 구성합니다. RelativeLayout도 LinearLayout만큼 많이 쓰이는 레이아웃이며, LinearLayout에 비해 각 요소의 위치를 조금 더 세밀하게 조정하는 것이 가능하기에 복잡한 화면을 구성할 때 주로 쓰입니다.

RelativeLayout은 LinearLayout처럼 레이아웃 자체에서 지정해주는 속성은 따로 없으며, 레이아웃 내의 요소들이 가지는 속성에 따라 각 요소의 위치가 결정됩니다. 아래에 RelativeLayout 내의 요소들이 가질 수 있는 속성들을 정리해 보았습니다.

레이아웃 내 요소들간의 관계를 지정하는 속성
  • Layout above : 해당 요소가 이곳에 지정한 ID를 가지는 요소의 바로 위에 위치하도록 합니다.
  • Layout below : 해당 요소가 이곳에 지정한 ID를 가지는 요소의 바로 아래에 위치하도록 합니다.
  • Layout to left of : 해당 요소가 이곳에 지정한 ID를 가지는 요소의 바로 왼쪽에 위치하도록 합니다.
  • Layout to right of : 해당 요소가 이곳에 지정한 ID를 가지는 요소의 바로 오른쪽에 위치하도록 합니다.
  • Layout align left : 해당 요소의 왼쪽 끝선을 이곳에 지정한 ID를 가지는 요소의 왼쪽 끝선과 일치시킵니다.
  • Layout align right : 해당 요소의 오른쪽 끝선을 이곳에 지정한 ID를 가지는 요소의 오른쪽 끝선과 일치시킵니다.
  • Layout align top : 해당 요소의 윗선을 이곳에 지정한 ID를 가지는 요소의 윗선과 일치시킵니다.
  • Layout align bottom : 해당 요소의 아랫선을 이곳에 지정한 ID를 가지는 요소의 아랫선과 일치시킵니다.

레이아웃과 요소간의 관계를 지정하는 속성
  • Layout align parent left : 해당 요소의 왼쪽 끝선을 parent(레이아웃)의 왼쪽 끝과 일치시킵니다.
  • Layout align parent right : 해당 요소의 오른쪽 끝선을 레이아웃의 오른쪽 끝과 일치시킵니다.
  • Layout align parent top : 해당 요소의 윗선을 레이아웃의 윗선과 일치시킵니다.
  • Layout align parent bottom : 해당 요소의 아랫선을 레이아웃의 아랫선과 일치시킵니다.

RelativeLayout은 각 요소들의 위치를 세밀하게 지정할 수 있기에, 이처럼 속성들이 좀 많습니다. 하지만 이 속성들만 이해한다면 얼마든지 복잡한 레이아웃도 만들 수 있으니 잘 알아두도록 하세요. 아래는 RelativeLayout을 이용하여 레이아웃을 구성한 예입니다.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />
<EditText android:text="EditText" 
	android:id="@+id/EditText01" 
	android:layout_width="wrap_content" 
	android:layout_height="wrap_content" 
	android:layout_alignParentRight="true"/>

<Button android:text="Button" 
	android:id="@+id/Button01" 
	android:layout_width="wrap_content" 
	android:layout_height="wrap_content" 
	android:layout_toLeftOf="@+id/EditText01" 
	android:layout_below="@+id/EditText01"/>
	
</RelativeLayout>

EditText는 레이아웃 오른쪽에 위치하도록, Button은 EditText의 왼쪽 아래에 위치하도록 지정한 모습





3. FrameLayout

FrameLayout은 각 요소들을 모두 왼쪽 상단을 기준으로 포개는 방식으로 배치합니다. 주로 탭(Tab)을 이용할 때 자주 사용됩니다. 

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />
<EditText android:text="EditText" 
	android:id="@+id/EditText01" 
	android:layout_width="wrap_content" 
	android:layout_height="wrap_content" 
	/>

<Button android:text="Button" 
	android:id="@+id/Button01" 
	android:layout_width="wrap_content" 
	android:layout_height="wrap_content" 
	/>
	
</FrameLayout>

FrameLayout의 배치 모습. 각 요소들이 왼쪽 상단을 기준으로 겹쳐져 배치된 것을 확인할 수 있습니다.



4. AbsoluteLayout (Deprecated)

AbsoluteLayout은 그 이름에서도 알 수 있듯이 레이아웃 내의 요소이 배치될 "절대적인" 위치를 지정해주는 레이아웃입니다. 따라서, Portrait 모드에서 보이던 요소가 Landscape 모드에서는 화면에 보이지 않게 될 수 있습니다. 이 레이아웃은 현재 Deprecated 상태로, 가급적 사용하지 않는 것이 좋습니다.

<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    android:layout_y="0px" android:layout_x="0px"/>
<EditText android:text="EditText" 
	android:id="@+id/EditText01" 
	android:layout_width="wrap_content" 
	android:layout_height="wrap_content" 
	android:layout_x="100px" android:layout_y="300px"/>

<Button android:text="Button" 
	android:id="@+id/Button01" 
	android:layout_width="wrap_content" 
	android:layout_height="wrap_content" 
	android:layout_x="30px" android:layout_y="30px"/>
	
</AbsoluteLayout>

Portrait 모드일 때의 모습. 모든 요소가 화면에 표시되고 있습니다.



Landscape 모드일 때의 화면. EditText의 위치가 x=100px, y=300px 이므로 이 모드에서는 보이지 않습니다.



5. TableLayout

TableLayout 또한 이름에서 알 수 있듯이 표 형태의 레이아웃을 제공합니다. 일정한 선에 맞추어 정렬되어야 하는 요소 (다이얼 버튼 등)를 정렬 할 때 주로 사용합니다.

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TableRow
   		android:layout_width="fill_parent"
   		android:layout_height="wrap_content">
		
		<TextView  
		    android:layout_width="wrap_content" 
		    android:layout_height="wrap_content" 
		    android:text="Text" />
		
		<EditText android:text="EditText" 
			android:id="@+id/EditText01" 
			android:layout_width="wrap_content" 
			android:layout_height="wrap_content" />
			
	</TableRow>
	
	<TableRow
   		android:layout_width="fill_parent"
   		android:layout_height="wrap_content">

		<Button android:text="Button" 
			android:id="@+id/Button01" 
			android:layout_width="wrap_content" 
			android:layout_height="wrap_content" />
			
		<Button android:text="Button" 
			android:id="@+id/Button02" 
			android:layout_width="wrap_content" 
			android:layout_height="wrap_content" />
		
	</TableRow>
</TableLayout>
행의 구분은 TableRow 태그로 구분하며, 각 열의 너비는 그 열 안의 요소들의 너비에 따라 결정됩니다. 위에서는 열의 너비를 각각이 최소로 가지는 크기 (wrap_content)가 되도록 지정하였습니다.



6. ScrollView

한 화면에 표시해야 할 내용이 많을 경우 사용합니다. 리스트에서 내용이 많아지면 스크롤바가 생기는 것처럼, ScrollView 내에의 요소들이 한 화면에 표시되기 어려울 만큼 공간을 많이 차지한다면 스크롤바를 표시하여 스크롤을 통해 한 화면에 표시되지 않는 요소를 볼 수 있게 해줍니다.

ScrollView는 단 하나의 요소만을 포함할 수 있으므로, ScrollView에 요소들을 넣기 전에 해당 요소들은 모드 LinearLayout이나 RelativeLayout 등의 레이아웃에 미리 포함시켜 놓고, 그 레이아웃이 ScrollView의 하위 요소로 포함되도록 구성하여야 합니다.

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    
    <LinearLayout
    	android:layout_width="fill_parent"
    	android:layout_height="fill_parent"
    	android:orientation="vertical">
		
		<TextView  
		    android:layout_width="wrap_content" 
		    android:layout_height="wrap_content" 
		    android:text="Text" />
		
		<EditText android:text="EditText" 
			android:id="@+id/EditText01" 
			android:layout_width="wrap_content" 
			android:layout_height="wrap_content" />
		
		<Button android:text="Button" 
			android:id="@+id/Button01" 
			android:layout_width="wrap_content" 
			android:layout_height="wrap_content" />
			
		<Button android:text="Button" 
			android:id="@+id/Button02" 
			android:layout_width="wrap_content" 
			android:layout_height="wrap_content" />
		
		<ToggleButton android:id="@+id/ToggleButton01" 
			android:layout_width="wrap_content" 
			android:layout_height="wrap_content" />
		
		<DatePicker android:id="@+id/DatePicker01" 
			android:layout_width="wrap_content" 
			android:layout_height="wrap_content"/>
		
		<TimePicker android:id="@+id/TimePicker01" 
			android:layout_width="wrap_content" 
			android:layout_height="wrap_content"/>
			
	</LinearLayout>

</ScrollView>

화면 오른쪽에 스크롤바가 생긴 것을 확인할 수 있습니다.