본문 바로가기
Android

[깡쌤의 안드로이드 프로그래밍 with 자바 - 2022 - 쌤즈] 정리 12 - LinearLayout

by 들풀민들레 2022. 5. 9.

책의 모든 내용을 저자 직강으로 진행한 강의는 ssamz.com 에서 들으실 수 있습니다.

본 글은 [깡쌤의 안드로이드 프로그래밍 with 자바 - 2022 - 쌤즈] 의 내용을 발췌한 것입니다.
좀더 자세한 내용은 책 혹은 인강(www.ssamz.com)을 통해 확인해 주세요.

 

4.1. LinearLayout


4.1.1. LinearLayout 소개


가장 많이 이용되는 레이아웃 중 하나가 LinearLayout입니다. LinearLayout은 해당 레이아웃에
포함된 뷰를 순서대로 가로나 세로 방향으로 나열합니다. 따라서 다른 레이아웃에는 없는, 방향을
지정하는 orientation 속성을 제공합니다.

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 1"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 2"/>
</LinearLayout>

LinearLayout에 Button 두 개를 포함하였고, orientation 속성을 "vertical"로 지정하였으므로 두
버튼은 세로 방향으로 나열됩니다. 만일, orientation 속성을 "horizontal"로 바꾸어 테스트하면 버튼
두 개가 가로 방향으로 나열됩니다

 

4.1.2. 레이아웃 중첩


이번에는 너무 유명한 카카오톡의 채팅 목록 화면을 작성한다고 가정해보겠습니다.

 


카카오톡 목록 화면 전체를 구성하려면 이번 장의 내용만으로는 불가능하고, 이후 살펴볼 RecyclerView의 Adapter라는 기능을 추가로 알아야 합니다. 이 부분은 이후에 다루고, 이번에는 위의 목록 화면에서
채팅방 하나의 내용을 표현하는 화면 구성 방법을 살펴보겠습니다.

 

그림처럼 항목을 구성해야 한다면 프로필 사진을 위한 ImageView와 이름, 내용, 날짜를 위한
TextView 3개가 필요합니다. 위 화면을 LinearLayout으로 구현할 수 있을까요? 여기서 중요한 것은
이름과 내용이 위아래로 나열되었다는 점입니다. 간단하게 생각하면 전체 뷰를 가로 방향으로 나열하고,
내용 TextView가 자동 개행되어 아래 방향으로 흐르면 될 것처럼 보입니다.
하지만 LinearLayout은 자동 개행을 제공하지 않습니다. 즉, 한번 가로 방향으로 지정하면 화면을
벗어나더라도 계속 가로로만 나열됩니다. 그렇다면 LinearLayout만으로는 위와 같은 화면을 구성할
수 없는 걸까요? LinearLayout을 하나만 사용하면 불가능하지만, 중첩하면 가능합니다. 즉, 레이아웃
클래스 하위에 다른 레이아웃 클래스를 배치하는 것입니다.

 

목록 화면을 구성하기 위해 전체 LinearLayout을 가로 방향으로 설정하고, 그 하위에 ImageView와
LinearLayout, TextView를 배치합니다. 그리고 하위 LinearLayout은 세로 방향으로 설정하여
TextView 두 개를 배치하면 됩니다. 이처럼 레이아웃 클래스에 레이아웃 클래스를 중첩하는 식으로
화면을 구성하면 위의 예보다 더 복잡한 화면도 구현할 수 있습니다.
생성되는 뷰 객체의 계층구조를 그려 보면 다음과 같습니다.

 

4.1.3. LinearLayout 속성


gravity와 layout_gravity
LinearLayout을 이용할 때 뷰가 정렬되는 위치를 신경 써야 할 때가 있습니다. 기본적으로 레이아웃에서 뷰의 위치는 왼쪽 위(Left- Top)인데요. 만일, 버튼을 LinearLayout 영역의 오른쪽 아래에 나타내려면 어떻게 해야 할까요?

 

 


안드로이드에서 뷰의 정렬과 관련된 속성은 gravity와 layout_gravity 두 가지입니다. 두 속성 모두 left, right, top, bottom 속성값 등을 설정할 수 있지만, 적용되는 대상은 다릅니다. gravity 속성은 뷰의 내용(content)을 뷰 영역 내에서 어디에 나타낼지를 설정하고, layout_gravity 속성은 뷰를 LinearLayout 영역 내에서 어디에 나타낼지를 설정합니다.

 

다음은 LinearLayout에 TextView를 하나 포함하고, 해당 뷰를 gravity와 layout_gravity 두 가지
방법으로 정렬한 예입니다.

 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="150dp"
android:layout_height="150dp"
android:text="HelloWorld"
android:background="#FF0000"
android:textColor="#FFFFFF"
android:layout_gravity="center_vertical|center_horizontal"
android:gravity="bottom|right"/>
</LinearLayout>

그림을 보면 gravity="bottom|right" 속성에 따라 TextView 영역 내에서 문자열이 오른쪽 아래에
잘 나옵니다. 그런데 layout_gravity="center_vertical|center_horizontal" 코드는 원하는
대로 정렬되지 않았습니다. 즉, TextView가 LinearLayout 영역 내에서 가로 방향으로는 가운데
정렬되었지만, 세로 방향으로는 가운데 정렬되지 않았습니다.


이유는 LinearLayout은 방향에 따라 포함된 뷰를 차례로 나열하므로 orientation 속성이
"vertical"이면, 세로 방향으로는 뷰가 포함된 순서대로 나열되어 세로 방향의 layout_gravity가
적용되지 않기 때문입니다. 반대로 orientation 속성이 "horizontal"이면 가로 방향의
layout _gravity가 적용되지 않습니다.


그렇다면 위의 예에서 LinearLayout을 사용하면서 TextView를 화면 중앙에 나오게는 못할까요?
물론 이후 살펴볼 RelativeLayout으로 배치하는 게 가장 편하지만, LinearLayout으로도 가능합니다.
TextView의 layout_gravity 속성을 이용하지 않고 LinearLayout의 gravity 속성을 이용하면 됩니다.
gravity 속성은 뷰 내부에서 내용(content)을 정렬하는 목적으로 사용되는데, LinearLayout에
적용하면 레이아웃에 포함된 뷰가 내용이 됩니다.

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<!--중략-->
</LinearLayout>

weight
LinearLayout에서 중요 속성이며 이용빈도도 높습니다. weight 속성은 여백과 관련이 있습니다.
레이아웃에 뷰를 배치하다 보면 가로나 세로 방향으로 여백이 발생할 수 있습니다. 이 여백을 화면에
배치된 뷰들이 확장해서 차지하게 할 때 이용됩니다.

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#FF0000"/>
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:background="#00FF00"/>
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#0000FF"/>
</LinearLayout>

위의 코드는 LinearLayout에 세로 방향으로 TextView 세 개를 나타낸 예입니다. 그런데 각 TextView의 layout_height를 보면 모두 0dp로 지정하였습니다. 크기를 0으로 지정하면 뷰는 영역을 차지하지 못하여 화면에서 안 보입니다. 결국, 모두 0dp로 지정하였으므로 화면 전체가 여백이 됩니다. 그런데 세 개의 TextView 모두 layout_weight를 설정하여 여백 확장 기법을 명시하였습니다.

 


각 뷰의 layout_weight 값을 1, 2, 1로 지정하였는데, layout_weight 값은 절대적 수치가 아닌 상대적으로 계산되는 값입니다. 모든 weight 값을 더해서 등분으로 계산됩니다. 즉, 1, 2, 1로 지정하였으므로 전체를 더하면 4가 되고, 첫 번째 TextView가 1/4, 두 번째 TextView가 2/4, 세 번째 TextView가 1/4의 여백을 차지하게 됩니다.

 

책의 모든 내용을 저자 직강으로 진행한 강의는 ssamz.com 에서 들으실 수 있습니다.