뷰를 배치하는 레이아웃 - LinearLayout

이윤설·2024년 8월 25일
0

안드로이드 앱은 다양한 뷰를 적절하게 배치해서 화면을 구성한다.
이때 뷰를 배치하는 클래스를 레이아웃 클래스라고 한다.
레이아웃 클래스는 그릇의 역할을 한다.
레이아웃 클래스는 저마다 배치 규칙이 있다.

선형으로 배치 - LinearLayout

배치 규칙

LinearLayout은 뷰를 가로나 세로 방향으로 나열하는 레이아웃 클래스다.
orientation 속성에 horiziontal 또는 vertical을 설정할 수 있다.


LinearLayout은 방향만 설정하면 뷰를 추가한 순서대로 나열한다.
만약 사진과 같은 화면을 구성해야 한다면 LinearLayout으로 구현할 수 있을까?

이 화면을 구성하려면 1개의 이미지 뷰와 3개의 텍스트 뷰가 필요하다.
그런데 만약 orientation을 horizontal로 지정하면 모든 뷰가 일렬로 표시될 것이다.

이럴 때는 LinearLayout을 중첩하면 가능하다.
레이아웃 클래스도 뷰이므로 다른 레이아웃 클래스에 포함할 수 있다.
즉, LinearLayout에 LinearLayout을 포함할 수 있다.

이처럼 LinearLayout은 특정한 방향으로 뷰를 배치하는 단순한 레이아웃이지만 레이아웃을 중첩할 때 진가를 발휘한다.

여백을 채우는 layout_weight 속성

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="BUTTON1" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="3"
        android:text="BUTTON2" />
</LinearLayout>

layout_weight의 동작 원리

layout_weight는 동일한 부모 레이아웃 내에서 자식 뷰 간의 비율을 나타낸다.
예를 들어, 두 개의 뷰가 각각 layout_weight="1"과 layout_weight="3"을 가진다면, 전체 가용 공간은 1 + 3 = 4로 계산된다.

그런 다음, 첫 번째 뷰는 전체 공간의 1/4(25%)을 차지하고, 두 번째 뷰는 3/4(75%)을 차지하게 된다.

중첩된 레이아웃에서 여백 채우기

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="BUTTON1" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            android:text="BUTTON2" />
    </LinearLayout>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="BUTTON3" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="BUTTON4" />
</LinearLayout>

  • BUTTON1과 BUTTON2에 설정한 가중치와 BUTTON3에 설정한 가중치가 서로 영향을 주지 않는다. 즉, layout_weight 속성은 같은 영역에 있는 뷰끼리만 여백을 나누어 차지한다.
  • 화면 전체를 감싸는 LinearLayout에 LinearLayout, BUTTON3, BUTTON4를 세로로 나열하고 BUTTON3에만 layout_weight를 1로 설정했으므로 세로 여백의 전체를 차지한다.

여백 채우기로 뷰의 크기 설정하기

<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="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:text="Button1" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:text="Button2" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:text="Button3" />
</LinearLayout>

  • layout_weight은 여백을 채우는 속성이지만, 뷰의 크기를 0으로 하고 layout_weight 값만 설정하기도 한다.
  • 위 코드는 layout_height를 0으로 설정했다. 뷰의 크기가 0이면 화면에 아무것도 안나온다. 즉, 화면 전체가 여백인 상태에서 각 버튼의 layout_weight를 1로 설정했다.
  • 따라서 결과는 세로 여백을 3등분해서 버튼을 표시한다.

뷰를 정렬하는 gravity, layout_gravity

뷰를 정렬할 때는 gravity와 layout_gravity를 사용한다.
만약 이 속성을 사용하지 않으면 기본값은 left/top이다. 즉, 왼쪽 위를 기준으로 정렬한다.

<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:background="#FF0000"
        android:text="HelloWorld"
        android:textColor="#FFFFFF"
        android:textSize="15dp"
        android:textStyle="bold" />
</LinearLayout>

현재는 gravity 설정을 안했기 때문에 기본값인 왼쪽 위에 정렬되었다.

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:layout_gravity="center_horizontal"
        android:background="#FF0000"
        android:gravity="right|bottom"
        android:text="HelloWorld"
        android:textColor="#FFFFFF"
        android:textSize="15dp"
        android:textStyle="bold" />
</LinearLayout>


gravity: 정렬 대상은 콘텐츠다. "HelloWorld" 문자열이 텍스트 뷰가 차지하는 영역에서 오른쪽 아래에 표시된다.
layout_gravity: 뷰 자체를 정렬한다. 따라서 텍스트 뷰 자체(빨간색 박스)가 가로로 가운데에 표시된다.

cf. orientation과 gravity

  1. orientation="vertical":

    • LinearLayout에서 orientation 속성은 자식 뷰들이 어떻게 배치될지를 결정한다.
    • vertical로 설정하면 자식 뷰들이 세로로 위에서 아래로 배치된다. 이때 자식 뷰들은 기본적으로 가로 방향으로 꽉 채워지며, 세로 방향으로는 순서대로 쌓인다.
  2. layout_gravity:

    • layout_gravity는 자식 뷰가 부모 LinearLayout 내에서 어떻게 배치될지를 결정한다.
    • 예를 들어, layout_gravity="center_horizontal"은 자식 뷰를 가로 방향 중앙에 배치한다. 이 속성은 자식 뷰의 위치를 부모 레이아웃 안에서 지정할 때 사용한다.
  3. layout_gravity="center_vertical"이 적용되지 않나?:

    • LinearLayout이 세로 방향(orientation="vertical")으로 설정된 경우, 자식 뷰는 이미 위에서 아래로 배치된다. 즉, 세로 방향으로는 이미 LinearLayout이 기본적으로 자식 뷰의 배치를 결정하고 있기 때문에, 추가적인 세로 정렬(center_vertical)은 효과가 없다.
    • 반면, 가로 방향 정렬(center_horizontal)은 부모 레이아웃 안에서 자식 뷰를 가로로 가운데에 배치할 수 있다.

정리:

  • LinearLayoutorientation 속성에 따라 layout_gravity의 적용 범위가 달라진다.
  • 세로 방향(vertical)으로 설정된 LinearLayout에서는 layout_gravity="center_vertical"이 이미 세로 배치가 고정되어 있어 의미가 없고, 가로 방향(horizontal)의 정렬만 영향을 미친다.

gravity와 layout_gravity 속성 적용하기 2

이번에는 빨간 박스를 화면의 정가운데에 위치시키려고 한다.
뷰를 화면 가운데에 표시하려면 레이아웃에 gravity="center"로 설정해야 한다.

<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">

    <TextView
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:background="#FF0000"
        android:gravity="right|bottom"
        android:text="HelloWorld"
        android:textColor="#FFFFFF"
        android:textSize="15dp"
        android:textStyle="bold" />
</LinearLayout>

코드에서 android:layout_gravity="center_horizontal"을 제거했다.
왜냐하면 이미 LinearLayout의 부모 레이아웃에서 android:gravity="center"를 사용하여 자식 뷰들을 화면 중앙으로 정렬했기 때문에 중복이기 때문이다.

profile
화려한 외면이 아닌 단단한 내면

0개의 댓글