일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- DART
- textfield
- android
- Navigation
- scroll
- LifeCycle
- livedata
- TEST
- 계측
- appbar
- viewmodel
- Flutter
- textview
- Kotlin
- 테스트
- Button
- Dialog
- tabbar
- CustomScrollView
- drift
- ScrollView
- data
- Coroutines
- intent
- 안드로이드
- Compose
- 앱
- activity
- binding
- 앱바
- Today
- Total
Study Record
[안드로이드] ConstraintLayout 살펴보기 본문
😶 ConstraintLayout
ConstraintLayout 은 평면 보기 계층 구조가 있는 크로 복잡한 레이아웃을 만들 수 있는 ViewGroup 에 속한다. 하위 뷰들 간의 연결 또는 정렬(제약 조건) 이 존재하며, 뷰마다 하나 이상의 수평, 수직 제약 조건을 정의해야 한다.
😶 기본
ConstraintLayout 을 ViewGroup 으로 갖는 모든 View 는 수평, 수직 제약 조건을 하나씩 정의해야 한다. 제약 조건을 부여하는 방법은 app:layout_constraint[방향]_to[방향]Of 속성으로 값은 "parent" 혹은 같은 하위 요소의 id 값으로 한다. "parent" 는 부모 ConstraintLayout 를 의미한다.(즉, 오른쪽 끝, 왼쪽 끝, 맨 상단, 맨 하단)
[방향] 에는 bottom, start, end, top 중 4가지 값을 가질 수 있는데 start 와 end 는 언어를 읽을 때 시작 방향이 오른쪽이면 start 가 오른쪽이 되고, 읽는 방향의 시작이 왼쪽이면 start 는 왼쪽이 된다. 한국어에서는 start 가 왼쪽, end 가 오른쪽이다.
app:layout_constraint[방향1]_to[방향2]of 에서 [방향1]은 자기 자신이고 [방향2]는 제약을 걸 상대라고 생각하면 된다. 예를 들어, app:layout_constraintStart_toEndOf="parent" 이면 수평 제약은 왼쪽 벽이 된다. [방향1] 과 [방향2] 는 같은 수평 또는 수직상에서만 가능하다. app:layout_constraintStart_toBottomOf 는 불가능하다.
예시)
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/view1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
...
android:text="Hello World!"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/view2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="20dp"
...
android:text="Hello World!"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/view1"/>
</androidx.constraintlayout.widget.ConstraintLayout>
view1 의 수평 조건은 오른쪽 벽과 왼쪽 벽에 위치해야 하니 그 중간의 가운데로 위치된 것이고, 수직 조건은 위쪽 벽에 붙어야 하므로 상단에 위치해 있다.
view2 의 수평 조건은 view1 과 같이 오른쪽 벽과 왼쪽 벽에 위치하는데 너비의 크기가 "0dp" 이니까 늘릴 수 있을 만큼 너비 크기가 늘어난다. view2 의 수직조건은 자기 자신의 위쪽(Top)이 상대(view1)의 아래쪽(Bottom)에 붙어야 하므로 view1 의 아래에 위치한다.
😶 chain
View 끼리 서로를 제약 조건을 걸면 chain 이 생성될 수 있다. 이렇게 서로 체인이 맺어지면 Head 에서 체인 속성을 정할 수 있는데 다음 보기와 같은 수평적 체인은 add:layout_constraintHoriaontal_chainStyle , 수직적 체인은 add:layout_constraintVertical_chainStyle 으로 정할 수 있다.
체인 종류 - spread , spread_inside , packed (기본값)
예시 코드)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="@style/NameStyle"
tools:context=".MainActivity">
<View
android:id="@+id/container"
android:layout_width="160dp"
android:layout_height="200dp"
android:background="@color/gray"
android:layout_margin="20dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/text_view_1"
android:layout_width="0dp"
android:layout_height="30dp"
android:text="textView1"
android:background="@color/purple_200"
android:layout_marginHorizontal="20dp"
app:layout_constraintVertical_chainStyle="spread"
app:layout_constraintBottom_toTopOf="@+id/text_view_2"
app:layout_constraintStart_toEndOf="@+id/container"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/container"/>
<TextView
android:id="@+id/text_view_2"
android:layout_width="0dp"
android:layout_height="30dp"
android:text="textView2"
android:background="@color/purple_200"
android:layout_marginHorizontal="20dp"
app:layout_constraintBottom_toTopOf="@+id/text_view_3"
app:layout_constraintTop_toBottomOf="@+id/text_view_1"
app:layout_constraintStart_toEndOf="@+id/container"
app:layout_constraintEnd_toEndOf="parent"/>
<TextView
android:id="@+id/text_view_3"
android:layout_width="0dp"
android:layout_height="30dp"
android:text="textView3"
android:background="@color/purple_200"
android:layout_marginHorizontal="20dp"
app:layout_constraintBottom_toBottomOf="@+id/container"
app:layout_constraintStart_toEndOf="@+id/container"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_view_2" />
</androidx.constraintlayout.widget.ConstraintLayout>
😶 가중치
서로 체인으로 연결된 상태에서 수직 체인일 경우, app:layout_constraintVertical_weight (가중치)를 사용하고 높이를 0dp 로 주면 연결된 체인의 가중치에 따라 높이가 결정된다.
수평 체인일 경우, app:layout_constraintHorizontal_weight 속성은 너비를 0dp 로 주면 각각 가중치 값에 따라 너비가 결정된다.
예시) textView1 : textView2 : textView3 = 2 : 2 : 1 의 가중치를 가질 경우
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<View
android:id="@+id/container"
android:layout_width="160dp"
android:layout_height="200dp"
android:background="@color/gray"
android:layout_margin="20dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/text_view_1"
android:layout_width="0dp"
android:layout_height="0dp"
android:text="textView1"
android:background="@color/purple_500"
android:layout_marginHorizontal="20dp"
app:layout_constraintVertical_weight="2"
app:layout_constraintBottom_toTopOf="@+id/text_view_2"
app:layout_constraintStart_toEndOf="@+id/container"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/container"/>
<TextView
android:id="@+id/text_view_2"
android:layout_width="0dp"
android:layout_height="0dp"
android:text="textView2"
android:background="@color/purple_200"
android:layout_marginHorizontal="20dp"
app:layout_constraintVertical_weight="2"
app:layout_constraintBottom_toTopOf="@+id/text_view_3"
app:layout_constraintTop_toBottomOf="@+id/text_view_1"
app:layout_constraintStart_toEndOf="@+id/container"
app:layout_constraintEnd_toEndOf="parent"/>
<TextView
android:id="@+id/text_view_3"
android:layout_width="0dp"
android:layout_height="0dp"
android:text="textView3"
android:background="@color/teal_200"
android:layout_marginHorizontal="20dp"
app:layout_constraintVertical_weight="1"
app:layout_constraintBottom_toBottomOf="@+id/container"
app:layout_constraintStart_toEndOf="@+id/container"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_view_2"/>
</androidx.constraintlayout.widget.ConstraintLayout>
😶 bias
서로 "packed" 로 연결된 체인에서 app:layout_constraintVertical_bias (수직 체인) 혹은 app:layout_constraintHorizontal_bias (수평 체인) 를 사용하면 편향된 위치를 조절할 수 있다. 값은 0 ~1 로 설정할 수 있고 0 이면 start(상단) 에 위치하고 1 이면 end(하단) 에 위치한다.
체인뿐만 아니라 수직적으로 또는 수평적으로 제약 관계를 가지고 있을 때 bias 를 설정하지 않을 땐 관계를 맺은 요소의 가운데에 위치한다. 하지만 bias 를 설정하면 가운데뿐만 아니라 편향된 위치를 가지게 할 수 있다. (ex. 가운데는 0.5 , 상단은 0 , 하단은 1 등등)
예시)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="@style/NameStyle"
tools:context=".MainActivity">
<View
android:id="@+id/container"
android:layout_width="160dp"
android:layout_height="300dp"
android:background="@color/gray"
android:layout_margin="20dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/text_view_1"
android:layout_width="0dp"
android:layout_height="40dp"
android:text="textView1"
android:background="@color/purple_500"
android:layout_marginHorizontal="20dp"
app:layout_constraintVertical_bias="0.7"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintBottom_toTopOf="@+id/text_view_2"
app:layout_constraintStart_toEndOf="@+id/container"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/container"/>
<TextView
android:id="@+id/text_view_2"
android:layout_width="0dp"
android:layout_height="40dp"
android:text="textView2"
android:background="@color/purple_200"
android:layout_marginHorizontal="20dp"
app:layout_constraintBottom_toTopOf="@+id/text_view_3"
app:layout_constraintTop_toBottomOf="@+id/text_view_1"
app:layout_constraintStart_toEndOf="@+id/container"
app:layout_constraintEnd_toEndOf="parent"/>
<TextView
android:id="@+id/text_view_3"
android:layout_width="0dp"
android:layout_height="40dp"
android:text="textView3"
android:background="@color/teal_200"
android:layout_marginHorizontal="20dp"
app:layout_constraintBottom_toBottomOf="@+id/container"
app:layout_constraintStart_toEndOf="@+id/container"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_view_2"/>
</androidx.constraintlayout.widget.ConstraintLayout>
😶 BaseLine 제약 조건
BaseLine 제약 조건은 보기 텍스트의 기준선을 다른 보기 텍스트의 기준선과 정렬한다. 텍스트가 포함된 뷰를 위치시킬 때 기준선을 사용하지 않으면 텍스트가 서로 이어지지 않은 것처럼 보일 수 있다.
다음 예시로 "how" 는 글씨가 크고 "small textView" 는 글씨가 작은 텍스트 뷰로 "how" 를 "small textView" 의 bottom 에 맞췄을 때는 "small textView" 가 아래쪽인 것처럼 보이고 "how" 가 상단과 하단을 연결해 가운데에 위치하면 "small textView" 가 살짝 떠있는 것처럼 보인다.
예시) baseLine 에 맞췄을 경우
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp"
tools:context=".MainActivity">
<TextView
android:id="@+id/label_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="how"
android:textSize="35sp"
android:textStyle="bold"
app:layout_constraintBaseline_toBaselineOf="@+id/info_text"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/info_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text=" small textView"
android:gravity="start"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@+id/label_text" />
</androidx.constraintlayout.widget.ConstraintLayout>
😶 가이드 라인 이용하기
화면을 꾸미기 전에 가이드 라인(선)을 미리 그려놓고 그 기준에 맞게 하위 요소들을 배치시킬 수도 있다. orientation 속성으로 가로선 혹은 세로선인지 정하고 layout_constraintGuide_percent로 start(ex. 상단 or 왼쪽) 으로부터 어디로 위치할지 0 ~ 1 사이값으로 위치시킬 수 있다.
가이드라인은 실제 화면에 보이는 요소가 아니다. 다른 요소를 배치시키기 위한 도구일 뿐이다.
다음 예시의 가이드라인은 딱 정 중앙에 가로선의 가이드라인이다.
<androidx.constraintlayout.widget.Guideline
android:id="@+id/gl_width_line"
android:layout_width="1dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent=".5" />
app:layout_constraintGuide_begin 은 시작점(보통 상단 혹은 왼쪽) 에서부터 얼마만큼 떨어졌는지로 가이드라인을 위치시킬 수 있다. (app:layout_constraintGuide_end 는 끝점(하단 혹은 오른쪽)에서 떨어진 거리)
<androidx.constraintlayout.widget.Guideline
android:id="@+id/gl_begin"
android:layout_width="1dp"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="24dp" />
예시) 가로선, 세로선이 포함된 화면
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/gl_width_line"
android:layout_width="wrap_content"
android:layout_height="1dp"
android:orientation="horizontal"
app:layout_constraintGuide_percent=".5" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/gl_height_line"
android:layout_width="1dp"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent=".8" />
<TextView
android:id="@+id/label_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="how"
android:textSize="35sp"
android:textStyle="bold"
app:layout_constraintBaseline_toBaselineOf="@+id/info_text"
app:layout_constraintEnd_toStartOf="@+id/info_text"/>
<TextView
android:id="@+id/info_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" small textView"
android:gravity="start"
app:layout_constraintBottom_toTopOf="@+id/gl_width_line"
app:layout_constraintEnd_toEndOf="@+id/gl_height_line" />
</androidx.constraintlayout.widget.ConstraintLayout>
😶 너비, 높이 비율로 설정하기
너비, 높이의 비율로 요소를 그리고 싶다면 app:layout_constraintDimensionRatio 속성을 사용할 수 있다.
너비와 높이 둘 중 하나가 "0dp"(match_parent) 로 설정하거나 둘 다 "0dp" 로 설정해야 한다.
app:layout_constraintDimensionRatio="1:1" 과 같은 형식으로 사용할 수 있는데 기본적으로 "width:height" 비율이다. 1:1 이면 가로와 세로의 길이가 동일한 요소를 그릴 수 있다.
app:layout_constraintDimensionRatio="H,3:7" 과 같이 앞의 "H" 와 "W" 가 붙을 수 있는데 "H" 면 높이를 제약한다는 의미이고 "W" 면 너비를 제약한다는 의미이다. 만약 높이를 제약한다면 너비의 값이 정해진 상태에서 높이의 크기를 비율에 맞게 적용하겠다는 의미이고, 너비를 제약한다면 높이의 값이 정해진 상태에서 너비의 크기를 비율에 맞게 적용하겠다는 의미이다.
예시)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/gl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.2"/>
<View
android:id="@+id/view1"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@color/gray"
app:layout_constraintDimensionRatio="H,6:1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<View
android:id="@+id/view2"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@color/gray"
app:layout_constraintDimensionRatio="W,2:1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@+id/gl"
app:layout_constraintStart_toStartOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
view1 은 수평적으로 너비의 크기가 정해진 상태로 "H,6:1" 이므로 너비의 1/6 만큼 높이의 길이로 한다는 의미가 된다.
view2 는 수직적으로 높이의 크기가 정해진 상태로 "W,2:1" 이므로 높이의 2배만큼 너비의 길이로 한다는 의미가 된다.
'안드로이드' 카테고리의 다른 글
[안드로이드] Fragment 살펴보기 (0) | 2023.06.22 |
---|---|
[안드로이드] 데이터 바인딩(Data binding)과 뷰 바인딩(View binding) (0) | 2023.06.19 |
[안드로이드] 키보드 내리기/올리기/Activity 시작 시 자동으로 올리기 (0) | 2023.06.16 |
[안드로이드] EditText 살펴보기 (0) | 2023.06.16 |
[안드로이드] style 과 theme (0) | 2023.06.15 |