RelativeLayout으로 레이아웃을 구성하는 방법을 설명합니다.
RelativeLayout
RelativeLayout은 부모(Parent) View 또는 자식(Child) View의 상대적 위치 관계를 정의하여 UI를 배치하는 Layout입니다.
LinearLayout은 가로 또는 세로 방향으로 View가 순서대로 배치되었지만 RelativeLayout은 객체간의 상대적인 위치 관계를 정의하지 않으면 배치가 되지 않습니다.
이번 튜토리얼에서는 RelativeLayout의 기본적인 내용에 대해서 알아보겠습니다.
프로젝트 생성하기
[File] >> [New] >> [New Project]
에서 Empty Activity를 선택하시고 새 프로젝트를 생성해주세요.
프로젝트를 생성하면 자동적으로 MainActivity.java
와 activity_main.xml
파일이 생성됩니다. MainActivity.java
코드를 보면 activity_main.xml
으로 UI Layout을 정의하도록 코드가 입력되어있습니다.
위치 관계를 정의하지 않는 경우
RelativeLayout은 객체의 상대적인 위치관계를 정의해야 합니다. 상대적인 위치를 정의하지 않으면 기본적으로 가로축은 부모의 왼쪽, 세로축은 부모의 위쪽으로 정의가 됩니다.
예제를 통해서 알아보겠습니다. 아래 코드를 /res/layout/activity_main.xml
에 입력하시고 결과를 확인해주세요.
RelativeLayout 객체는 TextView 객체 2개를 포함하고 있습니다. 그리고 상대적인 위치는 아무것도 정의되지 않았습니다.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.codestudio.myapplication.MainActivity">
<TextView
android:layout_width="200dp"
android:layout_height="30dp"
android:text="TextView01"
android:background="#80cbc4"/>
<TextView
android:layout_width="30dp"
android:layout_height="200dp"
android:text="TextView02"
android:gravity="center"
android:background="#e0e0e0"/>
</RelativeLayout>
결과를 보면 TextView01 위에 TextView02가 쌓여있는 형태로 배치가 되었습니다.
RelativeLayout은 상대적인 위치가 정의되어있지 않으면 가로축은 부모 왼쪽, 세로축은 부모 위쪽으로 설정됩니다. 그래서 두개의 View가 모두 왼쪽과 위쪽에 배치되었습니다.
그리고 RelativeLayout은 View의 위치를 정할 때, XML 코드의 위에서 아래 순서로 정합니다. 그래서 첫번째로 정의된 TextView01이 먼저 배치되고 그 뒤에 TextView02가 배치되어 TextView01의 일부가 가려졌습니다.
부모(상위) 객체에 상대적인 위치
부모 객체와의 상대적인 위치를 관계를 정의하여 자식 객체의 위치를 정할 수 있습니다. 예를들어 부모의 좌측 상단에 배치, 부모의 중앙에 배치, 부모의 우측 하단에 배치 등 처럼 부모를 기준으로 자식 View의 위치를 정의할 수 있습니다.
아래의 속성들을 사용하여 부모 객체에 상대적인 위치 관계를 정의할 수 있습니다.
XML attributes | |
---|---|
layout_alignParentTop | 부모의 상단에 객체를 배치 |
layout_alignParentBottom | 부모의 하단에 객체를 배치 |
layout_alignParentRight | 부모의 우측에 객체를 배치 |
layout_alignParentLeft | 부모의 좌측에 객체를 배치 |
layout_centerHorizontal | 부모의 가로축 중앙에 객체를 배치 |
layout_centerVertical | 부모의 세로축 중앙에 객체를 배치 |
layout_centerInParent | 부모의 가로, 세로 축 중앙에 객체를 배치 |
예제로 자세히 알아보겠습니다. 아래 코드를 입력하시고 결과를 확인해주세요.
RelativeLayout은 9개의 TextView를 포함하고 있고 각 객체는 부모의 상대적인 위치가 2개씩 정의되어 있습니다.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.codestudio.myapplication.MainActivity">
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:text="TextView01"
android:background="#80cbc4"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true" />
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:text="TextView02"
android:background="#e0e0e0"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"/>
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:text="TextView03"
android:background="#ababab"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"/>
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:text="TextView04"
android:background="#a1887f"
android:layout_centerVertical="true"/>
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:text="TextView05"
android:background="#ff8a65"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"/>
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:text="TextView06"
android:background="#81c784"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"/>
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:text="TextView07"
android:background="#29b6f6"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"/>
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:text="TextView08"
android:background="#5c6bc0"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"/>
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:text="TextView09"
android:background="#f06292"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"/>
</RelativeLayout>
아래 그림은 안드로이드 스튜디오의 Preview 화면입니다. 점선과 화살표가 있어 객체가 잘 배치되었는지 확인하기 좋습니다.
TextView01은 layout_alignParentTop
과 layout_alignParentLeft
이 true로 설정되었습니다. alignParentTop은 부모의 위쪽에 배치시키라는 의미이고, alighParentLeft는 부모의 왼쪽에 배치시키라는 의미입니다. 그래서 부모의 좌측 상단에 배치되었습니다.
TextView02는 layout_alignParentTop
과 layout_centerHorizontal
이 true로 설정되었습니다. 부모의 상단과 가로축 중앙에 배치시키라는 의미입니다.
TextView03의 경우 layout_alignParentTop
과 layout_alignParentRight
이 true로 설정되었습니다. 부모의 상단과 오른쪽에 배치시키라는 의미입니다.
TextView04, ..., TextView09도 부모의 상대적인 위치에 배치하도록 설정되었습니다.
자식(하위) 객체들에 상대적인 위치
부모뿐만 아니라 자식 객체 간의 상대적인 위치도 정의할 수 있습니다.
아래의 속성들을 사용하여 자식 객체들에 상대적인 위치 관계를 정의할 수 있습니다.
XML attributes | |
---|---|
layout_above | 어떤 자식 객체의 상단에 배치 |
layout_below | 어떤 자식 객체의 하단에 배치 |
layout_toRightOf | 어떤 자식 객체의 우측에 배치 |
layout_toLeftOf | 어떤 자식 객체의 좌측에 배치 |
예제로 자세히 알아보겠습니다. 아래 코드를 입력하시고 결과를 확인해주세요.
RelativeLayout 객체는 4개의 TextView객체를 포함하고 있습니다.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.codestudio.myapplication.MainActivity">
<TextView
android:id="@+id/tv01"
android:layout_width="100dp"
android:layout_height="100dp"
android:text="TextView01"
android:gravity="center"
android:background="#80cbc4"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true" />
<TextView
android:id="@+id/tv02"
android:layout_width="100dp"
android:layout_height="100dp"
android:text="TextView02"
android:gravity="center"
android:background="#ababab"
android:layout_toRightOf="@id/tv01"
android:layout_below="@id/tv01"/>
<TextView
android:id="@+id/tv03"
android:layout_width="100dp"
android:layout_height="100dp"
android:text="TextView03"
android:gravity="center"
android:background="#ff8a65"
android:layout_toRightOf="@id/tv02"
android:layout_above="@id/tv02"/>
<TextView
android:id="@+id/tv04"
android:layout_width="100dp"
android:layout_height="100dp"
android:text="TextView04"
android:gravity="center"
android:background="#29b6f6"
android:layout_toLeftOf="@id/tv03"
android:layout_below="@id/tv02"/>
</RelativeLayout>
TextView01은 부모의 좌측 상단에 배치하였습니다. 그리고 id="@+id/tv01"
로 id를 설정하였습니다. id는 Layout에서 고유한 것으로 객체를 식별할 수 있게 합니다. id는 id="@+id/이름"
으로 선언하고 사용할 때는 @id/이름
으로 +
를 빼고 사용합니다.
TextView02는 id를 tv02
로 선언하였고 layout_toRightOf="@id/tv01"
, layout_below="@id/tv01"
의 속성을 설정하였습니다. layout_toRightOf는 어떤 객체의 오른쪽에 배치하겠다는 의미이고 layout_below는 어떤 객체의 아래쪽에 배치하겠다는 의미입니다. 따라서, TextView02는 id가 tv01인 객체의 오른쪽과 아래쪽에 배치시키겠다는 의미입니다. 결과를 보시면 TextView01의 오른쪽과 아래쪽에 배치되었습니다.
TextView03은 id를 tv03
으로 선언하였고 상대적인 위치는 id가 tv02인 객체의 오른쪽과 위쪽에 배치하도록 설정하였습니다. 결과를 보시면 TextView02의 오른쪽 상단에 배치되었습니다.
TextView04의 경우 tv03의 왼쪽, tv02의 아래쪽에 배치하도록 설정하였습니다. 결과를 보시면 설정대로 배치되었습니다.
부모와 자식 객체들에 상대적인 위치
부모의 상대적인 위치와, 자식 객체들의 상대적인 위치를 함께 적용할 수 도 있습니다.
예제로 확인해보겠습니다. 아래 코드를 입력하시고 결과를 확인해주세요.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.codestudio.myapplication.MainActivity">
<TextView
android:id="@+id/tv01"
android:layout_width="100dp"
android:layout_height="100dp"
android:text="TextView01"
android:gravity="center"
android:background="#80cbc4"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true" />
<TextView
android:layout_width="100dp"
android:layout_height="30dp"
android:text="TextView02"
android:gravity="center"
android:background="#80cb00"
android:layout_toRightOf="@id/tv01"/>
<TextView
android:layout_width="30dp"
android:layout_height="100dp"
android:text="TextView03"
android:gravity="center"
android:background="#80cb00"
android:layout_below="@id/tv01"/>
<TextView
android:id="@+id/tv04"
android:layout_width="100dp"
android:layout_height="100dp"
android:text="TextView04"
android:gravity="center"
android:background="#ff8a65"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"/>
<TextView
android:layout_width="100dp"
android:layout_height="30dp"
android:text="TextView05"
android:gravity="center"
android:background="#ababab"
android:layout_toRightOf="@id/tv04"/>
<TextView
android:layout_width="30dp"
android:layout_height="100dp"
android:text="TextView06"
android:gravity="center"
android:background="#ababab"
android:layout_below="@id/tv04"/>
<TextView
android:layout_width="100dp"
android:layout_height="30dp"
android:text="TextView07"
android:gravity="center"
android:background="#29b6f6"
android:layout_toRightOf="@id/tv04"
android:layout_centerVertical="true"/>
<TextView
android:layout_width="30dp"
android:layout_height="100dp"
android:text="TextView08"
android:gravity="center"
android:background="#29b6f6"
android:layout_below="@id/tv04"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
TextView01(tv01)은 부모의 좌상단에 배치하였습니다. TextView02는 tv01의 오른쪽, TextView03은 tv01의 아래쪽에 배치되었습니다.
TextView04(tv04)는 부모의 정 가운데 배치하였습니다. TextView05는 tv04의 오른쪽에 배치하였고, TextView06은 tv05의 아래족에 배치하였습니다. 결과를 보면 이전처럼 Text04에 TextView05, 06이 붙어있지 않네요. 그 이유는 상대적인 위치를 1개만 정의했기 때문에 가로축과 세로축이 기본적으로 부모의 왼쪽, 위쪽으로 자동설정되었기 떄문입니다.
TextView07은 tv4의 오른쪽, 그리고 부모의 세로축 중앙에 배치하도록 설정하였습니다. 결과를 보면 TextView04 바로 옆에 붙게 되었습니다.
TextView08은 tv4의 아래쪽, 그리고 부모의 가로축 중앙에 배치하도록 설정하였습니다. 결과를 보면 TextView04 바로 밑에 붙게 설정되었습니다.
라인 정렬하여 배치
이전 예제에서 TextView07은 TextView04의 오른쪽 중앙에 배치되었습니다. 만약 TextView04의 위쪽 라인에 맞추어 배치를 하고 싶은 경우가 있습니다.
아래의 속성들을 사용하여 객체들을 동일 라인에 정렬하여 배치할 수 있습니다.
XML attributes | |
---|---|
layout_alignTop | 객체들을 상단 라인에 정렬하여 배치 |
layout_alignBottom | 객체들을 하단 라인에 정렬하여 배치 |
layout_alignLeft | 객체들을 좌측 라인에 정렬하여 배치 |
layout_alignRight | 객체들을 우측 라인에 정렬하여 배치 |
layout_alignTop
, layout_alignLeft
, layout_alignRight
, layout_alignBottom
속성은 객체의 어떤 라인을 다른 객체의 동일 라인에 맞추어 배치를 할 수 있도록 도와줍니다.
예제로 자세히 알아보겠습니다. 아래 코드를 입력하시고 결과를 확인해주세요.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.codestudio.myapplication.MainActivity">
<TextView
android:id="@+id/tv01"
android:layout_width="100dp"
android:layout_height="100dp"
android:text="TextView01"
android:gravity="center"
android:background="#ff8a65"
android:layout_centerInParent="true"/>
<TextView
android:layout_width="100dp"
android:layout_height="30dp"
android:text="TextView02"
android:gravity="center"
android:background="#29b6f6"
android:layout_toRightOf="@id/tv01"
android:layout_centerVertical="true"/>
<TextView
android:layout_width="30dp"
android:layout_height="100dp"
android:text="TextView03"
android:gravity="center"
android:background="#29b6f6"
android:layout_below="@id/tv01"
android:layout_centerHorizontal="true"/>
<TextView
android:layout_width="100dp"
android:layout_height="30dp"
android:text="TextView04"
android:gravity="center"
android:background="#ababab"
android:layout_alignTop="@id/tv01"
android:layout_toRightOf="@id/tv01"/>
<TextView
android:layout_width="100dp"
android:layout_height="30dp"
android:text="TextView05"
android:gravity="center"
android:background="#ababab"
android:layout_alignBottom="@id/tv01"
android:layout_toRightOf="@id/tv01"/>
<TextView
android:layout_width="30dp"
android:layout_height="100dp"
android:text="TextView06"
android:gravity="center"
android:background="#ababab"
android:layout_alignLeft="@id/tv01"
android:layout_below="@id/tv01"/>
<TextView
android:layout_width="30dp"
android:layout_height="100dp"
android:text="TextView07"
android:gravity="center"
android:background="#ababab"
android:layout_alignRight="@id/tv01"
android:layout_below="@id/tv01"/>
</RelativeLayout>
TextView01은 layout_centerInParent
을 true로 설정하였습니다. layout_centerInParent
는 layout_centerVertical
와 layout_centerHorizontal
을 모두 적용하는 속성입니다.
TextView02와 TextView03은 이전 예제와 동일하게 배치하였습니다.
TextView04는 layout_alignTop="@id/tv01"
을 설정하여 tv01의 상단 라인과 자신의 상단라인을 맞추어 배치하도록 설정하였습니다. 결과를 보면 TextView04의 상단 라인과 TextView01의 상단라인이 정렬되어 배치된 것을 볼 수 있습니다.
TextView05는 layout_alignBottom="@id/tv01"
을 설정하여 tv01의 하단 라인과 자신의 하단라인을 맞추어 배치하도록 설정하였습니다.
TextView06는 layout_alignLeft="@id/tv01"
을 설정하여 tv01의 왼쪽 라인과 자신의 왼쪽 라인을 맞추어 배치하도록 설정하였습니다.
TextView06는 layout_alignRight="@id/tv01"
을 설정하여 tv01의 오른쪽 라인과 자신의 오른쪽 라인을 맞추어 배치하도록 설정하였습니다.
Baseline(기준선)에 맞추어 배치
문자열에서 Baseline이란, 아래 그림처럼 기준이 되는 선을 말합니다.
layout_alignBaseline
속성은 객체를 다른 객체의 baseline에 정렬하여 배치할 수 있게 합니다.
예제로 자세히 알아보겠습니다. 아래 코드를 입력하시고 결과를 확인해주세요.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.codestudio.myapplication.MainActivity">
<TextView
android:id="@+id/tv01"
android:layout_width="100dp"
android:layout_height="100dp"
android:text="TextView01"
android:gravity="center"
android:background="#ff8a65"
android:layout_centerInParent="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView02"
android:textSize="15sp"
android:background="#29b6f6"
android:layout_toLeftOf="@id/tv01"
android:layout_alignBaseline="@id/tv01"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView03"
android:background="#29b6f6"
android:textSize="20sp"
android:layout_toRightOf="@id/tv01"
android:layout_alignBaseline="@id/tv01"/>
</RelativeLayout>
TextView01은 부모의 중앙에 배치되었고, TextView02와 TextView03은 layout_alignBaseline="@id/tv01"
로 설정되었습니다. 결과를 보면 3개의 객체의 baseline이 동일선상에 정렬되어 배치된 것을 볼 수 있습니다.
정리
RelativeLayout에 대해서 간단히 알아보았고 UI Layout을 정의하는 방법을 살펴보았습니다.
튜토리얼에서 사용한 코드는 GitHub: Layout 기본 속성에서 확인하실 수 있습니다.
참고
Related Posts
- Android 14 - 사진/동영상 파일, 일부 접근 권한 소개
- Android - adb push, pull로 파일 복사, 다운로드
- Android 14 - 암시적 인텐트 변경사항 및 문제 해결
- Jetpack Compose - Row와 Column
- Android 13, AOSP 오픈소스 다운로드 및 빌드
- Android 13 - 세분화된 미디어 파일 권한
- Android 13에서 Notification 권한 요청, 알림 띄우기
- Android 13에서 'Access blocked: ComponentInfo' 에러 해결
- 에러 해결: android gradle plugin requires java 11 to run. you are currently using java 1.8.
- 안드로이드 - 코루틴과 Retrofit으로 비동기 통신 예제
- 안드로이드 - 코루틴으로 URL 이미지 불러오기
- Android - 진동, Vibrator, VibrationEffect 예제
- Some problems were found with the configuration of task 에러 수정
- Query method parameters should either be a type that can be converted into a database column or a List
- 우분투에서 Android 12 오픈소스 다운로드 및 빌드
- Android - ViewModel을 생성하는 방법
- Android - Transformations.map(), switchMap() 차이점
- Android - Transformations.distinctUntilChanged() 소개
- Android - TabLayout 구현 방법 (+ ViewPager2)
- Android - 휴대폰 전화번호 가져오는 방법
- Android 12 - Splash Screens 알아보기
- Android 12 - Incremental Install (Play as you Download) 소개
- Android - adb 명령어로 bugreport 로그 파일 추출
- Android - adb 명령어로 App 데이터 삭제
- Android - adb 명령어로 앱 비활성화, 활성화
- Android - adb 명령어로 특정 패키지의 PID 찾기
- Android - adb 명령어로 퍼미션 Grant 또는 Revoke
- Android - adb 명령어로 apk 설치, 삭제
- Android - adb 명령어로 특정 패키지의 프로세스 종료
- Android - adb 명령어로 screen capture 저장
- Android - adb 명령어로 System 앱 삭제, 설치
- Android - adb 명령어로 settings value 확인, 변경
- Android 12 - IntentFilter의 exported 명시적 선언
- Android - adb 명령어로 공장초기화(Factory reset)
- Android - adb logcat 명령어로 로그 출력