SlideShare a Scribd company logo
지금은 Constraint layout 시대
발표자
안세원 (kingori@gmail.com)
● 카카오모빌리티 안드로이드 앱 개발자
● GDG Korea
○ #android, #pangyo 채널 죽돌이
● 최근 참여 앱
○ 카카오 T 택시 기사용
○ 카카오 T
○ 카카오톡
2
ConstraintLayout
● 복잡한 레이아웃을 단순한 계층구조를 이용해 표현할 수 있는 ViewGroup
● 형제 View 들과의 관계를 정의해서 레이아웃을 구성한다는 점은
RelativeLayout과 비슷하지만, 보다 유연하고 다양한 기능을 제공함
https://developer.android.com/training/constraint-layout/index.html 3
왜 써야 하죠?
● RelativeLayout 에선 불가능했던 자식 뷰 간의 상호 관계 정의 가능
ex) 두 View를 위 아래로 붙여서 컨테이너 중앙에 배치하기
● LinearLayout을 써야만 했던 뷰 비율 조절도 간단히 가능
● 뷰 계층을 간단하게 할 수 있어 유지보수도 좋고 성능도 좋고!
4
다루는 내용
 ConstraintLayout 1.1 의 거의 모든 기능
○ MATCH_CONSTRAINT
○ Dimension ratio
○ Percent
○ Bias
○ Guideline
○ Chain
○ Barrier
○ Placeholder
○ ConstraintSet
○ Group
5
layout_constraintLeft_toLeftOf
layout_constraintLeft_toRightOf
layout_constraintRight_toLeftOf
layout_constraintRight_toRightOf
layout_constraintTop_toTopOf
layout_constraintTop_toBottomOf
layout_constraintBottom_toTopOf
layout_constraintBottom_toBottomOf
layout_constraintBaseline_toBaselineOf
layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf
 ConstraintLayout 1.1 의 거의 모든 기능
○ MATCH_CONSTRAINT
○ Dimension ratio
○ Percent
○ Bias
○ Guideline
○ Chain
○ Barrier
○ Placeholder
○ ConstraintSet
○ Group
다루는 내용
6
layout_constraintLeft_toLeftOf
layout_constraintLeft_toRightOf
layout_constraintRight_toLeftOf
layout_constraintRight_toRightOf
layout_constraintTop_toTopOf
layout_constraintTop_toBottomOf
layout_constraintBottom_toTopOf
layout_constraintBottom_toBottomOf
layout_constraintBaseline_toBaselineOf
layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf
 ConstraintLayout 1.1 의 거의 모든 기능
○ MATCH_CONSTRAINT
○ Dimension ratio
○ Percent
○ Bias
○ Guideline
○ Chain
○ Barrier
○ Placeholder
○ ConstraintSet
○ Group
다루는 내용
7
layout_constraintLeft_toLeftOf
layout_constraintLeft_toRightOf
layout_constraintRight_toLeftOf
layout_constraintRight_toRightOf
layout_constraintTop_toTopOf
layout_constraintTop_toBottomOf
layout_constraintBottom_toTopOf
layout_constraintBottom_toBottomOf
layout_constraintBaseline_toBaselineOf
layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf
 ConstraintLayout 1.1 의 거의 모든 기능
○ MATCH_CONSTRAINT
○ Dimension ratio
○ Percent
○ Bias
○ Guideline
○ Chain
○ Barrier
○ Placeholder
○ ConstraintSet
○ Group
다루는 내용
8
안다루는 내용
● Circular Positioning
● Optimizer
● Android Studio의 Layout editor 활용
9
릴리즈 이력
● 2017.2 : 1.0
● 2017.3 : 1.0.2
● 2018.4 : 1.1.0
● 20XX.X : 2.0 ?
10
Gradle 설정
repositories {
maven {
url 'https://maven.google.com'
}
}
dependencies {
compile 'com.android.support.constraint:constraint-layout:1.1.0'
}
11
1장
천리길도 View 하나부터
Constraint
● ConstraintLayout에서 자식 뷰의 위치를 잡는 기준
● 다른 뷰나 부모 레이아웃과의 정렬 조건 / 연결 관계를 나타냄
● layout_constraint[기준1]_to[기준2]of="[viewId|parent]"
● start, end 속성은 left, right 속성보다 우선됨
<Button android:id="@+id/buttonB" ...
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toLeftOf="@id/buttonA"
app:layout_constraintBottom_toBottomOf="parent"/>
13
Constraint
● RelativeLayout의 alignLeft / toLeftOf 와는 다름
○ constraint는 위치/ 크기의 기준을 잡는 역할일 뿐
○ 이와 달리 RelativeLayout의 align 등은 위치 자체를 정의함
● Top/Bottom/Left/Right를 모두 선언해야 하는 것은 아님
ex) android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
→ 부모 뷰 좌상단 정렬
○ 하지만 체인 등 다른 기능 사용시 예상치 못한 동작이 발생할 수 있음!
 가급적 4방향 모두 선언하는 습관을 들이자
14
뷰 크기
● android:layout_width / layout_height 속성 사용
○ 고정 크기 ex) android:layout_width="100dp"
○ wrap_content
○ match_constraint
● match_parent가 아닌 match_constraint!
○ 크기는 0dp : constraint에 꽉 차게 크기를 맞춤
○ match_constraint라는 속성 값은 없다! → 0dp 이라 쓰고 match_constraint라고 읽음
○ 제대로 동작하려면 뷰의 양쪽 constraint를 다 선언해줘야 함 (ex. left 와 right)
● match_parent는 사용하지 말 것!
○ 1.0.0 beta-5 에선 아예 예외를 던졌으나, 다음 버전에서 수정되었음
○ 그래도 권장하지 않으니 사용하지 말 것
15
뷰 크기
<Button
android:layout_width="150dp"
android:layout_height="0dp"
android:text="HAHA"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
16
뷰 크기 - Percent size
● 부모 뷰의 크기에 비례하여 뷰의 크기를 결정함
○ 단, padding은 제외한 크기!
● layout_width 는 match_constraint로 선언
● layout_constraint[Width|Height]_default: 대상 축의 constraint의 계산 방식
○ spread: constraint 영역에 맞춤 (기본 동작)
○ wrap: 뷰의 크기에 맞춤
○ percent: constraint[Width|Height]_percent 속성에 선언한 비율에 맞춤
android:layout_width="0dp"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="0.4"
17
뷰 크기 – 가로/세로 비율 지정
● dimensionRatio : 뷰의 가로/세로 비율 결정
○ app:layout_constraintDimensionRatio="1" → 가로/세로 = 1/1
○ app:layout_constraintDimensionRatio="1:1" → 가로:세로 = 1:1
● 적어도 한 방향은 match_constraint 여야 함!
● 두 방향 모두 match_constraint 일 경우, 비율에 맞춰 constraint 내에서 가장
큰 크기로 설정
18
뷰 크기 – 가로/세로 비율 지정
<Button
android:layout_width="150dp"
android:layout_height="0dp"
android:text="HAHA"
app:layout_cDimensionRatio="1:1"/>
<Button
android:layout_width="0dp"
android:layout_height="0dp"
android:text="HAHA"
app:layout_cDimensionRatio="2"/>
<Button
android:layout_width="wrap_content"
android:layout_height="0dp"
android:text="HAHA"
app:layout_cDimensionRatio="1:2"/>
19
뷰 크기 – 가로/세로 비율 지정
● 명시적으로 비율을 적용할 축을 지정할 수 있음 : (W|H,)[비율]
○ W: 높이에 맞춰 폭을 조정
○ H: 폭에 맞춰 높이를 조정
● 폭 match_constraint, 높이 match_constraint인 경우
○ H,1:2: 폭을 constraint에 맞춰 설정한 후, 비율에 따라 높이를 결정
○ W,1:2: 높이를 constraint에 맞춰 설정한 후, 비율에 따라 폭을 결정
● 폭 wrap_content, 높이 match_constraint인 경우
○ H,1:2: 폭을 wrap_content에 맞춰 설정한 후, 비율에 따라 높이를 결정
○ W,1:2: 폭이 wrap_content로 결정되어 버렸기 때문인지 역으로 2:1 비율이 설정되어 버림(??)
20
뷰 크기 – 가로/세로 비율 지정
<Button
android:layout_width="0dp"
android:layout_height="0dp"
android:text="HAHA"
app:layout_cDimensionRatio
="W,1:2"/>
<Button
android:layout_width="0dp"
android:layout_height="0dp"
android:text="HAHA"
app:layout_cDimensionRatio
="H,1:2"/>
 넘쳐버림
<Button
android:layout_width="wrap_content"
android:layout_height="0dp"
android:text="HAHA"
app:layout_cDimensionRatio
="W,1:2"/>
 2:1 이 되어버림
<Button
android:layout_width="wrap_content"
android:layout_height="0dp"
android:text="HAHA"
app:layout_cDimensionRatio
="H,1:2"/>
21
뷰 크기 - 최소/최대
● 최소/최대 크기 지정 : app:layout_constraintWidth_[min|max]="size"
● android:minWidth와 다른점
○ wrap_content 일 땐 android:[min|max]width 적용
○ mactch_constraint 일 땐 app:layout_constraintWidth_[min|max] 적용
<Button
android:layout_width="wrap_content"
android:minWidth="100dp"
app:layout_constraintWidth_min="200dp"
… />
<Button
android:layout_width="0dp"
android:maxWidth="100dp"
app:layout_constraintWidth_max="200dp"
… />
22
위치 지정 - bias
● bias: (constraint 영역 크기 - 뷰 크기) 를 분배하는 비율
○ app:layout_constraintHorizontal_bias="0~1"
■ 0: 왼쪽에 붙이기 / 1: 오른쪽에 붙이기 / 0.5: 중간에 위치 (기본값)
<Button
android:layout_width="wrap_content"
app:layout_constraintHorizontal_bias="0"
… />
<Button
android:layout_width="wrap_content"
app:layout_constraintHorizontal_bias="1"
… />
23
위치 지정 - guideline
● android.support.constraint.Guideline
○ 가로 또는 세로 축 방향을 가진 가상의 뷰
● 부모 뷰의 특정 위치를 기준점으로 삼을 때 사용
● 축, 위치 값을 속성으로 가짐
○ 축: android:orientation="[vertical|horizontal]"
○ 위치
■ app:layout_constraintGuide_begin : 시작 지점으로 부터의 거리
■ app:layout_constraintGuide_end : 끝 지점으로 부터의 거리
■ app:layout_constraintGuide_percent : 시작 지점으로 부터의 % 위치
24
위치 지정 - guideline
<android.support.constraint.Guideline
android:id="@+id/gd_left"
app:layout_constraintGuide_begin="100dp"
android:orientation="vertical"/>
<android.support.constraint.Guideline
android:id="@+id/gd_right"
app:layout_constraintGuide_end="50dp"
android:orientation="vertical"/>
<android.support.constraint.Guideline
android:id="@+id/gd_bottom"
app:layout_constraintGuide_percent="0.8"
android:orientation="horizontal"/>
<Button
app:layout_constraintLeft_toRightOf="@id/gd_left"
app:layout_constraintRight_toLeftOf="@id/gd_right"
app:layout_constraintBottom_toTopOf="@id/gd_bottom"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="0dp" android:layout_height="0dp"
android:text="Button"/>
25
2장
여러개의 뷰
체인
● 서로 연결되어 그룹으로 동작하는 뷰의 묶음
● 체인으로 연결된 뷰 끼리도 체인이 연결된 방향으로만 그룹으로 동작함
● 생성 조건: 마주보는 뷰끼리 마주보는 방향으로 서로 constraint를 설정함
A B
A B 체인?
right to left of B left to right of A O
right to left of B right to right of A X
right to left of B top to top of A X
27
체인
● 체인 스타일의 종류
https://developer.android.com/reference/android/support/constraint/ConstraintLayout.html#Chains
28
체인
● 체인 스타일 별 설정 방법
○ spread: 헤드에 app:layout_constraintHorizontal_chainStyle="spread" 선언
○ spread_inside: 헤드에 app:layout_constraintHorizontal_chainStyle="spread_inside" 선언
○ packed: 헤드에 app:layout_constraintHorizontal_chainStyle="packed" 선언
○ packed with bias: packed 헤드에 app:layout_constraintHorizontal_bias="0~1" 선언
○ weighted: match_constraint 인 뷰가 포함된 체인의 뷰에
app:layout_constraintHorizontal_weight 속성 선언
● 체인 헤드: 위치 상 체인의 가장 앞쪽(왼쪽 혹은 윗쪽)에 위치한 뷰
29
체인 - spread
● (체인의 constraint 영역 - 뷰 크기의 합) 을 균등분할하여 배치
● 체인 바깥 마진은 constraint 영역에서 제외
● 체인 안쪽 마진은 마진을 가진 뷰의 크기에 합산
<Button android:id="@+id/btn_a"
android:layout_width="100dp"
android:layout_marginLeft="50dp"
app:layout_cLeft_toLeftOf="parent"
app:layout_cRight_toLeftOf="@id/btn_b"
app:layout_cHorizontal_chainStyle="spread"/>
<Button android:id="@+id/btn_b"
android:layout_width="100dp"
android:layout_marginLeft="20dp"
app:layout_cLeft_toRightOf="@id/btn_a"
app:layout_cRight_toRightOf="parent"/>
constraint 영역 = 300 - 50 = 250
view 크기 = 100 + 100 + 20 = 220
간격 = (250 - 220 )/ 3 = 10
A의 왼쪽 = 50 + 10 = 60
B의 왼쪽 = 60 + 100 + 10 + 20 = 190
30
체인 - spread_inside
● 체인의 양 끝 뷰를 constraint영역의 양 끝에 배치하고, 나머지 뷰를 남는 공
간을 균등분할하여 배치
<Button android:id="@+id/btn_a"
android:layout_width="100dp"
android:layout_marginLeft="20dp"
app:layout_cLeft_toLeftOf="parent"
app:layout_cRight_toLeftOf="@id/btn_b"
app:layout_cHorizontal_chainStyle="spread_inside"/>
<Button android:id="@+id/btn_b"
android:layout_width="100dp"
android:layout_marginRight="20dp"
app:layout_cLeft_toRightOf="@id/btn_a"
app:layout_cRight_toRightOf="parent"/>
31
체인 - packed / packed biased
● 체인을 구성하는 각 뷰를 밀착하여 배열
● (constraint 영역) - (뷰 폭의 합) 을 bias에 따라 분배
<Button android:id="@+id/btn_a"
android:layout_width="100dp"
app:layout_cLeft_toLeftOf="parent"
app:layout_cRight_toLeftOf="@id/btn_b"
app:layout_cHorizontal_chainStyle="packed"/>
<Button android:id="@+id/btn_b"
android:layout_width="100dp"
android:layout_marginRight="20dp"
android:layout_marginLeft="20dp"
app:layout_cLeft_toRightOf="@id/btn_a"
app:layout_cRight_toRightOf="parent"/>
constraint 영역 = 300 - 20 = 280
view 크기 = 100 + 100 + 20 = 220
남는 공간 = (280 - 220 )/ 2 = 30
A의 왼쪽 = 30
B의 왼쪽 = 30 + 100 + 20 = 150
32
체인 - weighted
● 크기가 match_constraint인 뷰가 하나 이상 포함된 체인
● match_constraint 뷰에 app:layout_constraintHorizontal_weight 속성으로 비율을 지정
● 주의: 모든 match_constraint 뷰에 빠짐없이 weight 속성을 지정해야 함!
<Button android:id="@+id/btn_a"
android:layout_width="0dp"
app:layout_cLeft_toLeftOf="parent"
app:layout_cRight_toLeftOf="@id/btn_b"
app:layout_constraintHorizontal_weight="2"/>
<Button android:id="@+id/btn_b"
android:layout_width="0dp"
android:layout_marginRight="10dp"
android:layout_marginLeft="20dp"
app:layout_cLeft_toRightOf="@id/btn_a"
app:layout_cRight_toRightOf="parent"
app:layout_constraintHorizontal_weight="1"/>
뷰가 차지할 수 있는 크기
= 300 - 20 - 10 = 270
A의 크기 = 270 /3 * 2 = 180
B의 크기 = 270 /3 * 1 = 90
33
Barrier
● 여러 뷰의 가장자리 위치에 만드는 가상의 뷰
● 복잡한 양식 등을 만드는데 활용할 수 있음
34
Barrier
<TextView
android:id="@+id/tv_1" android:text="name:"
android:layout_width="wrap_content
android:layout_height="wrap_content"
app:layout_cTop_toTopOf="parent
app:layout_cLeft_toLeftOf="parent"
app:layout_cBottom_toBottomOf="parent"
app:layout_cRight_toRightOf="parent"
app:layout_cVertical_bias="0" app:layout_cHorizontal_bias="0"
android:layout_margin="8dp" />
<TextView
android:id="@+id/tv_2" android:text="passwd:" android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_cTop_toBottomOf="@id/tv_1" app:layout_cLeft_toLeftOf="parent"
app:layout_cBottom_toBottomOf="parent" app:layout_cRight_toRightOf="parent"
app:layout_cVertical_bias="0" app:layout_cHorizontal_bias="0"
android:layout_margin="8dp"/>
<android.support.constraint.Barrier
android:id="@+id/br_label"
android:layout_width="0dp"
android:layout_height="0dp"
app:barrierDirection="right"
app:constraint_referenced_ids="tv_1,tv_2" />
35
Group
● 여러 뷰의 visibility를 한꺼번에 조정
○ 그룹의 visibility를 바꾸면 그룹에 속한 모든 뷰의 visiblity가 바뀜
⇒ flat해진 구조 덕분에 여러개의 뷰의 visibility를 바꿔야 할 때 유용함
● 하나의 뷰가 여러 그룹에 속할 경우, xml에 마지막으로 선언된 그룹의
visibility를 따름
<android.support.constraint.Group
android:id="@+id/grp_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="tv_1,tv_3"
android:visibility="gone"/>
36
ConstraintSet
● 프로그램적으로 constraint를 만드는 기능
○ 일일이 바닥부터 만들어내거나
○ 다른 xml로 부터 constraint만 뽑아오거나
○ ConstraintLayout 인스턴스에서 뽑아오거나
● 만들어진 constraint를 ConstraintLayout에 적용할 수 있음
● 동적으로 ConstraintLayout의 모든 뷰 혹은 일부 뷰의 레이아웃을 갱신할 수
있음
● ConstraintSet은 constraint만 갱신하므로 constraint와 관련 없는 속성
(padding, text size, …)은 영향받지 않음
● TransitionManager.beginDelayedTransition() 을 이용하여 손쉽게 애니메이션
생성 가능
37
ConstraintSet
constraintSet2 = ConstraintSet()
constraintSet2.clone(content)
constraintSet2.connect(R.id.icon_2, ConstraintSet.TOP,
R.id.btn_layout1, ConstraintSet.TOP )
constraintSet2.constrainWidth(R.id.icon_2,
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 120f,
resources.displayMetrics).toInt())
...
38
ConstraintSet
● ConstraintSet A를 ConstraintSet B로 갱신한 경우
○ A엔 있으나 B에는 없는 뷰 : 이전 constraint 유지
○ A엔 없으나 B에는 있는 뷰 : 무시됨
○ A에선 V1, V2가 체인이었으나 B에선 V1만 언급하며, 체인 관계가 깨진 경우
: 체인 관계는 깨지며, V2 의 위치는 다시 설정됨
39
Placeholder
● 기존 뷰의 위치를 재조정하는 가상의 뷰
● Placeholder가 대체한 원래의 뷰는 사라짐
<Button android:id="@+id/btn" android:text="btn"
android:layout_width="wrap_content" android:layout_height="wrap_content"
app:layout_cTop_toTopOf="parent" app:layout_cLeft_toLeftOf="parent" />
<android.support.constraint.Placeholder android:id="@+id/ph_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_cRight_toRightOf="parent"
app:layout_cBottom_toBottomOf="parent"/>
ph_1.setContentId(R.id.btn) //ph_1 자리로 btn을 옮김
40
Placeholder - 용도
● 동일한 속성을 가진 뷰를 배치만 다른 레이아웃에서 재사용
→ 가로/세로 레이아웃에서 view를 중복해서 선언하지 않아도 됨
→ 하지만 view 크기 컨트롤에 문제가 있음
<ConstLayout>
<View1 id="@+id/v1"
attr1="v1"
attr2="v2" .../>
...
<include layout="holder"/>
</ConstLayout>
<merge>
<Placeholder
id="p1"
const1=".."
app:content="@id/v1">
... />
</merge>
<merge>
<Placeholder
id="p1"
const1=".."
app:content="@id/v1"/>
... />
</merge>
layout/holder.xmllayout/layout.xml layout-land/holder.xml
41
Placeholder - 용도
● Runtime에 하나 혹은 여러 뷰의 위치를 바꿈
● 그 용도로 ConstraintSet을 만들지 않았나?
○ xml 상에서 간단하게 선언할 수 있어 편함
○ 하나의 placeholder에 여러 뷰를 번갈아가며 위치시킬 수 있음
http://androidkt.com/constraintlayout/42
3장
심화학습
wrap_content
● 텍스트가 긴 TextView에선 wrap_content가 의도치 않게 동작할 수 있음
○ margin 무시됨
○ 측정해 보면 constraint 크기가 아닌 parent 크기까지 폭이 늘어남
<TextView
android:layout_width="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:text="asdfasdfasdlfjasdf;asdlf;jasd;flkjasdf;l..."
android:layout_margin="50dp"
android:maxLines="1" android:ellipsize="end" />
44
wrap_content
● wrap_content를 constraint 영역 내에 제대로 표현하려면 추가 설정 필요
○ 크기는 android:layout_width="wrap_content"
○ app:layout_constrainedWidth="true" 설정을 추가
○ 1.0.2 에선 match_constraint & layout_constraintWidth_default="wrap"
 이 조합은 1.1.0 에서 deprecate됨
<TextView
android:text="asdfasdfasdlfjasdf;asdlf;ja..."
android:layout_width="wrap_content"
app:layout_constraintedWidth="wrap"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_margin="50dp"
android:maxLines="1" android:ellipsize="end"/>
짧은 텍스트 긴 텍스트 45
패딩, 마진과 레이아웃의 관계
● 부모 뷰의 패딩은 constraint 영역에서 빼야 함
ex) 300dp 폭, 좌우 패딩 50dp 이라면 constraint 영역은 300-(50)*2 = 200dp
● guideline은 부모 뷰의 패딩을 적용한 위치에 만들어짐
46
패딩, 마진과 레이아웃의 관계
<android.support.constraint.ConstraintLayout
android:layout_width="300dp" android:layout_height="300dp"
android:paddingLeft="100dp" android:paddingRight=“50dp">
<android.support.constraint.Guideline
android:orientation="vertical"
app:layout_constraintGuide_begin="50dp" /> → padding+begin = 100 + 50 = 150dp 위치에 생성
<android.support.constraint.Guideline
android:orientation="vertical"
app:layout_constraintGuide_end="50dp"/> → width - padding - end = 300- 50 - 50
= 200dp 위치에 생성
<android.support.constraint.Guideline
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5"/> → paddingLeft + ( constraintWidth ) / 2
= 100 + ( 300- 100 - 50 ) / 2
= 100 + 75 = 175dp 위치에 생성
47
패딩, 마진과 레이아웃의 관계
● 체인이 아니어도 다른 뷰와 constraint 관계를 맺을 수 있으나, 상대 뷰의
margin은 고려되지 않음
→ margin까지 고려하려면 chain 관계를 가져야 함
<Button android:id="@+id/btn_a"
android:layout_width="wrap_content"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"/>
<Button
android:id="@+id/btn_b"
android:layout_width="wrap_content"
app:layout_cLeft_toRightOf="@id/btn_a"/>
 B는 A의 marginRight를 고려하지 않음
48
패딩, 마진과 레이아웃의 관계
● 다음 조건에서 자식 뷰의 왼쪽 좌표를 계산하시오
○ 부모 뷰: 폭 300dp , 패딩 30dp
○ 자식 뷰: 폭 50dp, 좌우 마진 20dp
■ left to parent, right to parent
■ horizontal bias 0.2
?
49
패딩, 마진과 레이아웃의 관계
● view의 왼쪽 좌표 계산식
viewLeft = constraintLeft + (constraintWidth - (viewWidth+marginSide) ) * bias + marginLeft
○ constraintLeft
■ parent일 경우: parent.Left + parent.PaddingLeft
■ 특정 view A 의 오른쪽을 기준으로 할 경우: (constraintLeft_toRightOf="A" )
a.right + a.marginRight*
* 둘이 packed chain style 관계일 때에만!
○ constraintWidth = constraintRight - constraintLeft
○ marginSide = marginLeft + marginRight
● viewWidth 가 constraintWidth 보다 크면 어떻게 될까?
→ viewLeft 가 음수가 되어 constraintLeft 보다 왼쪽에 위치할 수 있음
50
패딩, 마진과 레이아웃의 관계
● 다음 조건에서 자식 뷰의 왼쪽 좌표를 계산하시오
○ 부모 뷰: 폭 300dp , 패딩 30dp
○ 자식 뷰: 폭 50dp, 좌우 마진 20dp
■ left to parent, right to parent
■ horizontal bias 0.2
viewLeft = constraintLeft + (constraintWidth - (viewWidth+marginSide) ) * bias + marginLeft
= 30 + ( 300 - 30 -30 - (50 + 20 + 20 ) ) * 0.2 + 20
= 30 + ( 240 - 90 ) * 0.2 + 20
= 30 + 30 + 20 = 80
→ 50dp 위치에 barrier를 만들어서 확인해보자!
51
패딩, 마진과 레이아웃의 관계
<android.support.constraint.ConstraintLayout
android:layout_width="300dp" android:padding="50dp">
<TextView
android:layout_width="100dp"/>
<TextView
android:layout_width="300dp"
app:layout_cHorizontal_bias="0.5"/>
<TextView
android:layout_width="100dp"
android:layout_marginLeft="50dp"/>
→ constraint width = 300 - 50 - 50 = 200
viewLeft = 50 + (200 - 100) * 0.5 = 50 + 50 = 100dp
→ viewLeft = 50 + (200 - 300) * 0.5 = 50 - 50 = 0dp
주의: 실제로 그려질 땐 50dp 위치부터 그려지고
텍스트 앞쪽은 짤림 → padding 50dp 의 영향
→ viewLeft = 50 + (200 - (100 + 50)) * 0.5 + 50
= 50 + 25 + 50 = 125dp
52
바라보는 뷰가 gone인 경우 - 체인
● 사라진 뷰는 없었던 뷰 취급
○ 뷰 크기는 0dp, 뷰의 마진도 0dp 처리
● 체인 헤드는 사라져도 여전히 헤드 역할을 함
○ A-B-C 체인에서 A가 gone일 경우, B가 새로운 헤더가 될까?
 아니오. 여전히 A가 체인 헤더의 역할을 함
53
바라보는 뷰가 gone인 경우 – 비 체인
● 사라진 뷰는 크기와 마진은 0dp인 채로 위치함
● 사라진 뷰를 참조하던 뷰는 여전히 해당 뷰를 참조함
○ 하지만 bias값이 있을 경우 이상하게 동작함  버그인가??
Left to parent
Right to parent
No bias
Left to parent
Right to parent
Bias=0
54
바라보는 뷰가 gone인 경우 - layout_goneMargin
● layout_goneMargin* : 바라보는 뷰의 visibility가 gone일 때 적용되는 마진
ex) A-B-C 체인에서
○ A가 gone 일 경우: B의 layout_goneMarginLeft가 동작
○ C가 gone 일 경우: B의 layout_goneMarginRight가 동작
● marginLeft와 goneMarginLeft 둘 다 적용될 상황에선 어떻게 동작할까?
→ goneMargin이 우선순위가 높음
● A-B-C 체인에서 B, C 모두 layout_goneMarginLeft를 선언했고,
A, B 모두 gone 된다면 B의 layout_goneMarginLeft는 동작할까?
→ 동작하지 않음. gone 된 뷰의 속성은 의미없음
55
참고자료 - ReleaseNote
● http://tools.android.com/recent/constraintlayoutbeta5isnowavailable : match_parent 크래시 위협
● https://androidstudio.googleblog.com/2017/02/constraintlayout-10-is-now-available.html
● https://androidstudio.googleblog.com/2017/03/constraintlayout-101-is-now-available.html
● https://androidstudio.googleblog.com/2017/03/constraintlayout-102-is-now-available.html
● https://androidstudio.googleblog.com/2017/05/constraintlayout-110-beta-1-release.html
● https://androidstudio.googleblog.com/2017/10/constraintlayout-110-beta-2.html
. packed chain의 0dp, 이 버전부턴 match_constraint로 동작함
. app:layout_constrainedWidth="true|false" 추가
● https://androidstudio.googleblog.com/2017/10/constraintlayout-110-beta-3-is-now.html
. Circular constraints 추가
● https://androidstudio.googleblog.com/2017/12/constraintlayout-110-beta-4.html
● https://androidstudio.googleblog.com/2018/02/constraintlayout-110-beta-5.html
● https://androidstudio.googleblog.com/2018/03/constraintlayout-110-beta-6.html
● https://androidstudio.googleblog.com/2018/04/constraintlayout-110.html
56
참고자료 - 구글 자료
● https://android-developers.googleblog.com/2017/08/understanding-
performance-benefits-of.html
● https://www.youtube.com/watch?list=PLWz5rJ2EKKc9e0d55YHgJFHXNZbGH
EXJX&time_continue=1&v=OHcfs6rStRo
● https://developer.android.com/reference/android/support/constraint/Constr
aintLayout.html
● https://developer.android.com/training/constraint-layout/index.html
● https://codelabs.developers.google.com/codelabs/constraint-layout/#0
57
참고자료 - 기타
● https://constraintlayout.com/
● https://academy.realm.io/posts/360-andev-2017-nicolas-roard-advanced-
constraintlayout/
● https://academy.realm.io/kr/posts/constraintlayout-it-can-do-what-now/
● https://proandroiddev.com/creating-awesome-animations-using-constraintlayout-
and-constraintset-part-i-390cc72c5f75
● https://medium.com/@rafael_toledo/whats-new-in-constraint-layout-1-1-x-
f0bdd4dbdfb3
● http://androidkt.com/constraintlayout/
● https://gist.github.com/kingori/fa4a71bf4e844b02d772d8c6d667fd32#file-
constraintlayout-xml
● https://github.com/kingori/Droidknight_ConstraintLayout
58
Q & A
끝

More Related Content

PDF
오픈소스로 쉽게 따라해보는 Unreal과 IoT 연계 및 개발 방법 소개.pdf
PDF
Sentence structure
PPTX
UI아트 작업자를 위한 언리얼엔진4 UMG #1
PDF
Android ConstraintLayout
PPT
안드로이드스터디 4
PPTX
Java, android 스터티6
PPTX
Java, android 스터티7
PDF
iOS Auto Layout
오픈소스로 쉽게 따라해보는 Unreal과 IoT 연계 및 개발 방법 소개.pdf
Sentence structure
UI아트 작업자를 위한 언리얼엔진4 UMG #1
Android ConstraintLayout
안드로이드스터디 4
Java, android 스터티6
Java, android 스터티7
iOS Auto Layout

Similar to 지금은 Constraint layout 시대 (18)

PPTX
Unity Scroll View에 관하여
PDF
HIG for iOS: UI Element (Bars, Views, Controls)
PPTX
Android Study Summary 2-1
PPTX
모바일 개발자가 원하는 디자인 가이드
PPTX
다양한 Device 대응_방법
KEY
Android design guideline overview
PDF
[NEXT] Android 개발 경험 프로젝트 1일차 (Widget, Linear Layout)
PPTX
Android Study Summary 2-2
PDF
협업하는 디자이너 - #4 Android
PPTX
Android 개론
PPTX
앱 인벤터 2: 비전공자를 위한 안드로이드 앱 만들기
PDF
iOS Human Interface Guidelines 정리 (1)
PPTX
Xamarin android
PDF
허니컴 태블릿 디자인
PDF
[1A5]효율적인안드로이드앱개발
PDF
React Native를 사용한
 초간단 커뮤니티 앱 제작
PPT
Introducing Fragments
PDF
200819 NAVER TECH CONCERT 06_놓치기 쉬운 안드로이드 UI 디테일 살펴보기
Unity Scroll View에 관하여
HIG for iOS: UI Element (Bars, Views, Controls)
Android Study Summary 2-1
모바일 개발자가 원하는 디자인 가이드
다양한 Device 대응_방법
Android design guideline overview
[NEXT] Android 개발 경험 프로젝트 1일차 (Widget, Linear Layout)
Android Study Summary 2-2
협업하는 디자이너 - #4 Android
Android 개론
앱 인벤터 2: 비전공자를 위한 안드로이드 앱 만들기
iOS Human Interface Guidelines 정리 (1)
Xamarin android
허니컴 태블릿 디자인
[1A5]효율적인안드로이드앱개발
React Native를 사용한
 초간단 커뮤니티 앱 제작
Introducing Fragments
200819 NAVER TECH CONCERT 06_놓치기 쉬운 안드로이드 UI 디테일 살펴보기
Ad

More from Sewon Ann (9)

PDF
Flipper 불완전 정복
PDF
Android studio 디버거 조금 더 잘 쓰기
PDF
안드로이드 개발에 유용한 도구들
PDF
백엔드 서버 구축없이 모바일 앱앱 만들어보기
PDF
Framer js a/s talk
PDF
develop android app using intellij
PDF
ant로 안드로이드 앱을 자동으로 빌드하자
PDF
Google Hackathon Korea - hangout mafia
PPTX
Spring 3의 jsr 303 지원
Flipper 불완전 정복
Android studio 디버거 조금 더 잘 쓰기
안드로이드 개발에 유용한 도구들
백엔드 서버 구축없이 모바일 앱앱 만들어보기
Framer js a/s talk
develop android app using intellij
ant로 안드로이드 앱을 자동으로 빌드하자
Google Hackathon Korea - hangout mafia
Spring 3의 jsr 303 지원
Ad

지금은 Constraint layout 시대

  • 2. 발표자 안세원 (kingori@gmail.com) ● 카카오모빌리티 안드로이드 앱 개발자 ● GDG Korea ○ #android, #pangyo 채널 죽돌이 ● 최근 참여 앱 ○ 카카오 T 택시 기사용 ○ 카카오 T ○ 카카오톡 2
  • 3. ConstraintLayout ● 복잡한 레이아웃을 단순한 계층구조를 이용해 표현할 수 있는 ViewGroup ● 형제 View 들과의 관계를 정의해서 레이아웃을 구성한다는 점은 RelativeLayout과 비슷하지만, 보다 유연하고 다양한 기능을 제공함 https://developer.android.com/training/constraint-layout/index.html 3
  • 4. 왜 써야 하죠? ● RelativeLayout 에선 불가능했던 자식 뷰 간의 상호 관계 정의 가능 ex) 두 View를 위 아래로 붙여서 컨테이너 중앙에 배치하기 ● LinearLayout을 써야만 했던 뷰 비율 조절도 간단히 가능 ● 뷰 계층을 간단하게 할 수 있어 유지보수도 좋고 성능도 좋고! 4
  • 5. 다루는 내용  ConstraintLayout 1.1 의 거의 모든 기능 ○ MATCH_CONSTRAINT ○ Dimension ratio ○ Percent ○ Bias ○ Guideline ○ Chain ○ Barrier ○ Placeholder ○ ConstraintSet ○ Group 5
  • 9. 안다루는 내용 ● Circular Positioning ● Optimizer ● Android Studio의 Layout editor 활용 9
  • 10. 릴리즈 이력 ● 2017.2 : 1.0 ● 2017.3 : 1.0.2 ● 2018.4 : 1.1.0 ● 20XX.X : 2.0 ? 10
  • 11. Gradle 설정 repositories { maven { url 'https://maven.google.com' } } dependencies { compile 'com.android.support.constraint:constraint-layout:1.1.0' } 11
  • 13. Constraint ● ConstraintLayout에서 자식 뷰의 위치를 잡는 기준 ● 다른 뷰나 부모 레이아웃과의 정렬 조건 / 연결 관계를 나타냄 ● layout_constraint[기준1]_to[기준2]of="[viewId|parent]" ● start, end 속성은 left, right 속성보다 우선됨 <Button android:id="@+id/buttonB" ... app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintRight_toLeftOf="@id/buttonA" app:layout_constraintBottom_toBottomOf="parent"/> 13
  • 14. Constraint ● RelativeLayout의 alignLeft / toLeftOf 와는 다름 ○ constraint는 위치/ 크기의 기준을 잡는 역할일 뿐 ○ 이와 달리 RelativeLayout의 align 등은 위치 자체를 정의함 ● Top/Bottom/Left/Right를 모두 선언해야 하는 것은 아님 ex) android:layout_width=“wrap_content” android:layout_height=“wrap_content” app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toLeftOf="parent" → 부모 뷰 좌상단 정렬 ○ 하지만 체인 등 다른 기능 사용시 예상치 못한 동작이 발생할 수 있음!  가급적 4방향 모두 선언하는 습관을 들이자 14
  • 15. 뷰 크기 ● android:layout_width / layout_height 속성 사용 ○ 고정 크기 ex) android:layout_width="100dp" ○ wrap_content ○ match_constraint ● match_parent가 아닌 match_constraint! ○ 크기는 0dp : constraint에 꽉 차게 크기를 맞춤 ○ match_constraint라는 속성 값은 없다! → 0dp 이라 쓰고 match_constraint라고 읽음 ○ 제대로 동작하려면 뷰의 양쪽 constraint를 다 선언해줘야 함 (ex. left 와 right) ● match_parent는 사용하지 말 것! ○ 1.0.0 beta-5 에선 아예 예외를 던졌으나, 다음 버전에서 수정되었음 ○ 그래도 권장하지 않으니 사용하지 말 것 15
  • 17. 뷰 크기 - Percent size ● 부모 뷰의 크기에 비례하여 뷰의 크기를 결정함 ○ 단, padding은 제외한 크기! ● layout_width 는 match_constraint로 선언 ● layout_constraint[Width|Height]_default: 대상 축의 constraint의 계산 방식 ○ spread: constraint 영역에 맞춤 (기본 동작) ○ wrap: 뷰의 크기에 맞춤 ○ percent: constraint[Width|Height]_percent 속성에 선언한 비율에 맞춤 android:layout_width="0dp" app:layout_constraintWidth_default="percent" app:layout_constraintWidth_percent="0.4" 17
  • 18. 뷰 크기 – 가로/세로 비율 지정 ● dimensionRatio : 뷰의 가로/세로 비율 결정 ○ app:layout_constraintDimensionRatio="1" → 가로/세로 = 1/1 ○ app:layout_constraintDimensionRatio="1:1" → 가로:세로 = 1:1 ● 적어도 한 방향은 match_constraint 여야 함! ● 두 방향 모두 match_constraint 일 경우, 비율에 맞춰 constraint 내에서 가장 큰 크기로 설정 18
  • 19. 뷰 크기 – 가로/세로 비율 지정 <Button android:layout_width="150dp" android:layout_height="0dp" android:text="HAHA" app:layout_cDimensionRatio="1:1"/> <Button android:layout_width="0dp" android:layout_height="0dp" android:text="HAHA" app:layout_cDimensionRatio="2"/> <Button android:layout_width="wrap_content" android:layout_height="0dp" android:text="HAHA" app:layout_cDimensionRatio="1:2"/> 19
  • 20. 뷰 크기 – 가로/세로 비율 지정 ● 명시적으로 비율을 적용할 축을 지정할 수 있음 : (W|H,)[비율] ○ W: 높이에 맞춰 폭을 조정 ○ H: 폭에 맞춰 높이를 조정 ● 폭 match_constraint, 높이 match_constraint인 경우 ○ H,1:2: 폭을 constraint에 맞춰 설정한 후, 비율에 따라 높이를 결정 ○ W,1:2: 높이를 constraint에 맞춰 설정한 후, 비율에 따라 폭을 결정 ● 폭 wrap_content, 높이 match_constraint인 경우 ○ H,1:2: 폭을 wrap_content에 맞춰 설정한 후, 비율에 따라 높이를 결정 ○ W,1:2: 폭이 wrap_content로 결정되어 버렸기 때문인지 역으로 2:1 비율이 설정되어 버림(??) 20
  • 21. 뷰 크기 – 가로/세로 비율 지정 <Button android:layout_width="0dp" android:layout_height="0dp" android:text="HAHA" app:layout_cDimensionRatio ="W,1:2"/> <Button android:layout_width="0dp" android:layout_height="0dp" android:text="HAHA" app:layout_cDimensionRatio ="H,1:2"/>  넘쳐버림 <Button android:layout_width="wrap_content" android:layout_height="0dp" android:text="HAHA" app:layout_cDimensionRatio ="W,1:2"/>  2:1 이 되어버림 <Button android:layout_width="wrap_content" android:layout_height="0dp" android:text="HAHA" app:layout_cDimensionRatio ="H,1:2"/> 21
  • 22. 뷰 크기 - 최소/최대 ● 최소/최대 크기 지정 : app:layout_constraintWidth_[min|max]="size" ● android:minWidth와 다른점 ○ wrap_content 일 땐 android:[min|max]width 적용 ○ mactch_constraint 일 땐 app:layout_constraintWidth_[min|max] 적용 <Button android:layout_width="wrap_content" android:minWidth="100dp" app:layout_constraintWidth_min="200dp" … /> <Button android:layout_width="0dp" android:maxWidth="100dp" app:layout_constraintWidth_max="200dp" … /> 22
  • 23. 위치 지정 - bias ● bias: (constraint 영역 크기 - 뷰 크기) 를 분배하는 비율 ○ app:layout_constraintHorizontal_bias="0~1" ■ 0: 왼쪽에 붙이기 / 1: 오른쪽에 붙이기 / 0.5: 중간에 위치 (기본값) <Button android:layout_width="wrap_content" app:layout_constraintHorizontal_bias="0" … /> <Button android:layout_width="wrap_content" app:layout_constraintHorizontal_bias="1" … /> 23
  • 24. 위치 지정 - guideline ● android.support.constraint.Guideline ○ 가로 또는 세로 축 방향을 가진 가상의 뷰 ● 부모 뷰의 특정 위치를 기준점으로 삼을 때 사용 ● 축, 위치 값을 속성으로 가짐 ○ 축: android:orientation="[vertical|horizontal]" ○ 위치 ■ app:layout_constraintGuide_begin : 시작 지점으로 부터의 거리 ■ app:layout_constraintGuide_end : 끝 지점으로 부터의 거리 ■ app:layout_constraintGuide_percent : 시작 지점으로 부터의 % 위치 24
  • 25. 위치 지정 - guideline <android.support.constraint.Guideline android:id="@+id/gd_left" app:layout_constraintGuide_begin="100dp" android:orientation="vertical"/> <android.support.constraint.Guideline android:id="@+id/gd_right" app:layout_constraintGuide_end="50dp" android:orientation="vertical"/> <android.support.constraint.Guideline android:id="@+id/gd_bottom" app:layout_constraintGuide_percent="0.8" android:orientation="horizontal"/> <Button app:layout_constraintLeft_toRightOf="@id/gd_left" app:layout_constraintRight_toLeftOf="@id/gd_right" app:layout_constraintBottom_toTopOf="@id/gd_bottom" app:layout_constraintTop_toTopOf="parent" android:layout_width="0dp" android:layout_height="0dp" android:text="Button"/> 25
  • 27. 체인 ● 서로 연결되어 그룹으로 동작하는 뷰의 묶음 ● 체인으로 연결된 뷰 끼리도 체인이 연결된 방향으로만 그룹으로 동작함 ● 생성 조건: 마주보는 뷰끼리 마주보는 방향으로 서로 constraint를 설정함 A B A B 체인? right to left of B left to right of A O right to left of B right to right of A X right to left of B top to top of A X 27
  • 28. 체인 ● 체인 스타일의 종류 https://developer.android.com/reference/android/support/constraint/ConstraintLayout.html#Chains 28
  • 29. 체인 ● 체인 스타일 별 설정 방법 ○ spread: 헤드에 app:layout_constraintHorizontal_chainStyle="spread" 선언 ○ spread_inside: 헤드에 app:layout_constraintHorizontal_chainStyle="spread_inside" 선언 ○ packed: 헤드에 app:layout_constraintHorizontal_chainStyle="packed" 선언 ○ packed with bias: packed 헤드에 app:layout_constraintHorizontal_bias="0~1" 선언 ○ weighted: match_constraint 인 뷰가 포함된 체인의 뷰에 app:layout_constraintHorizontal_weight 속성 선언 ● 체인 헤드: 위치 상 체인의 가장 앞쪽(왼쪽 혹은 윗쪽)에 위치한 뷰 29
  • 30. 체인 - spread ● (체인의 constraint 영역 - 뷰 크기의 합) 을 균등분할하여 배치 ● 체인 바깥 마진은 constraint 영역에서 제외 ● 체인 안쪽 마진은 마진을 가진 뷰의 크기에 합산 <Button android:id="@+id/btn_a" android:layout_width="100dp" android:layout_marginLeft="50dp" app:layout_cLeft_toLeftOf="parent" app:layout_cRight_toLeftOf="@id/btn_b" app:layout_cHorizontal_chainStyle="spread"/> <Button android:id="@+id/btn_b" android:layout_width="100dp" android:layout_marginLeft="20dp" app:layout_cLeft_toRightOf="@id/btn_a" app:layout_cRight_toRightOf="parent"/> constraint 영역 = 300 - 50 = 250 view 크기 = 100 + 100 + 20 = 220 간격 = (250 - 220 )/ 3 = 10 A의 왼쪽 = 50 + 10 = 60 B의 왼쪽 = 60 + 100 + 10 + 20 = 190 30
  • 31. 체인 - spread_inside ● 체인의 양 끝 뷰를 constraint영역의 양 끝에 배치하고, 나머지 뷰를 남는 공 간을 균등분할하여 배치 <Button android:id="@+id/btn_a" android:layout_width="100dp" android:layout_marginLeft="20dp" app:layout_cLeft_toLeftOf="parent" app:layout_cRight_toLeftOf="@id/btn_b" app:layout_cHorizontal_chainStyle="spread_inside"/> <Button android:id="@+id/btn_b" android:layout_width="100dp" android:layout_marginRight="20dp" app:layout_cLeft_toRightOf="@id/btn_a" app:layout_cRight_toRightOf="parent"/> 31
  • 32. 체인 - packed / packed biased ● 체인을 구성하는 각 뷰를 밀착하여 배열 ● (constraint 영역) - (뷰 폭의 합) 을 bias에 따라 분배 <Button android:id="@+id/btn_a" android:layout_width="100dp" app:layout_cLeft_toLeftOf="parent" app:layout_cRight_toLeftOf="@id/btn_b" app:layout_cHorizontal_chainStyle="packed"/> <Button android:id="@+id/btn_b" android:layout_width="100dp" android:layout_marginRight="20dp" android:layout_marginLeft="20dp" app:layout_cLeft_toRightOf="@id/btn_a" app:layout_cRight_toRightOf="parent"/> constraint 영역 = 300 - 20 = 280 view 크기 = 100 + 100 + 20 = 220 남는 공간 = (280 - 220 )/ 2 = 30 A의 왼쪽 = 30 B의 왼쪽 = 30 + 100 + 20 = 150 32
  • 33. 체인 - weighted ● 크기가 match_constraint인 뷰가 하나 이상 포함된 체인 ● match_constraint 뷰에 app:layout_constraintHorizontal_weight 속성으로 비율을 지정 ● 주의: 모든 match_constraint 뷰에 빠짐없이 weight 속성을 지정해야 함! <Button android:id="@+id/btn_a" android:layout_width="0dp" app:layout_cLeft_toLeftOf="parent" app:layout_cRight_toLeftOf="@id/btn_b" app:layout_constraintHorizontal_weight="2"/> <Button android:id="@+id/btn_b" android:layout_width="0dp" android:layout_marginRight="10dp" android:layout_marginLeft="20dp" app:layout_cLeft_toRightOf="@id/btn_a" app:layout_cRight_toRightOf="parent" app:layout_constraintHorizontal_weight="1"/> 뷰가 차지할 수 있는 크기 = 300 - 20 - 10 = 270 A의 크기 = 270 /3 * 2 = 180 B의 크기 = 270 /3 * 1 = 90 33
  • 34. Barrier ● 여러 뷰의 가장자리 위치에 만드는 가상의 뷰 ● 복잡한 양식 등을 만드는데 활용할 수 있음 34
  • 35. Barrier <TextView android:id="@+id/tv_1" android:text="name:" android:layout_width="wrap_content android:layout_height="wrap_content" app:layout_cTop_toTopOf="parent app:layout_cLeft_toLeftOf="parent" app:layout_cBottom_toBottomOf="parent" app:layout_cRight_toRightOf="parent" app:layout_cVertical_bias="0" app:layout_cHorizontal_bias="0" android:layout_margin="8dp" /> <TextView android:id="@+id/tv_2" android:text="passwd:" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_cTop_toBottomOf="@id/tv_1" app:layout_cLeft_toLeftOf="parent" app:layout_cBottom_toBottomOf="parent" app:layout_cRight_toRightOf="parent" app:layout_cVertical_bias="0" app:layout_cHorizontal_bias="0" android:layout_margin="8dp"/> <android.support.constraint.Barrier android:id="@+id/br_label" android:layout_width="0dp" android:layout_height="0dp" app:barrierDirection="right" app:constraint_referenced_ids="tv_1,tv_2" /> 35
  • 36. Group ● 여러 뷰의 visibility를 한꺼번에 조정 ○ 그룹의 visibility를 바꾸면 그룹에 속한 모든 뷰의 visiblity가 바뀜 ⇒ flat해진 구조 덕분에 여러개의 뷰의 visibility를 바꿔야 할 때 유용함 ● 하나의 뷰가 여러 그룹에 속할 경우, xml에 마지막으로 선언된 그룹의 visibility를 따름 <android.support.constraint.Group android:id="@+id/grp_1" android:layout_width="wrap_content" android:layout_height="wrap_content" app:constraint_referenced_ids="tv_1,tv_3" android:visibility="gone"/> 36
  • 37. ConstraintSet ● 프로그램적으로 constraint를 만드는 기능 ○ 일일이 바닥부터 만들어내거나 ○ 다른 xml로 부터 constraint만 뽑아오거나 ○ ConstraintLayout 인스턴스에서 뽑아오거나 ● 만들어진 constraint를 ConstraintLayout에 적용할 수 있음 ● 동적으로 ConstraintLayout의 모든 뷰 혹은 일부 뷰의 레이아웃을 갱신할 수 있음 ● ConstraintSet은 constraint만 갱신하므로 constraint와 관련 없는 속성 (padding, text size, …)은 영향받지 않음 ● TransitionManager.beginDelayedTransition() 을 이용하여 손쉽게 애니메이션 생성 가능 37
  • 38. ConstraintSet constraintSet2 = ConstraintSet() constraintSet2.clone(content) constraintSet2.connect(R.id.icon_2, ConstraintSet.TOP, R.id.btn_layout1, ConstraintSet.TOP ) constraintSet2.constrainWidth(R.id.icon_2, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 120f, resources.displayMetrics).toInt()) ... 38
  • 39. ConstraintSet ● ConstraintSet A를 ConstraintSet B로 갱신한 경우 ○ A엔 있으나 B에는 없는 뷰 : 이전 constraint 유지 ○ A엔 없으나 B에는 있는 뷰 : 무시됨 ○ A에선 V1, V2가 체인이었으나 B에선 V1만 언급하며, 체인 관계가 깨진 경우 : 체인 관계는 깨지며, V2 의 위치는 다시 설정됨 39
  • 40. Placeholder ● 기존 뷰의 위치를 재조정하는 가상의 뷰 ● Placeholder가 대체한 원래의 뷰는 사라짐 <Button android:id="@+id/btn" android:text="btn" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_cTop_toTopOf="parent" app:layout_cLeft_toLeftOf="parent" /> <android.support.constraint.Placeholder android:id="@+id/ph_1" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_cRight_toRightOf="parent" app:layout_cBottom_toBottomOf="parent"/> ph_1.setContentId(R.id.btn) //ph_1 자리로 btn을 옮김 40
  • 41. Placeholder - 용도 ● 동일한 속성을 가진 뷰를 배치만 다른 레이아웃에서 재사용 → 가로/세로 레이아웃에서 view를 중복해서 선언하지 않아도 됨 → 하지만 view 크기 컨트롤에 문제가 있음 <ConstLayout> <View1 id="@+id/v1" attr1="v1" attr2="v2" .../> ... <include layout="holder"/> </ConstLayout> <merge> <Placeholder id="p1" const1=".." app:content="@id/v1"> ... /> </merge> <merge> <Placeholder id="p1" const1=".." app:content="@id/v1"/> ... /> </merge> layout/holder.xmllayout/layout.xml layout-land/holder.xml 41
  • 42. Placeholder - 용도 ● Runtime에 하나 혹은 여러 뷰의 위치를 바꿈 ● 그 용도로 ConstraintSet을 만들지 않았나? ○ xml 상에서 간단하게 선언할 수 있어 편함 ○ 하나의 placeholder에 여러 뷰를 번갈아가며 위치시킬 수 있음 http://androidkt.com/constraintlayout/42
  • 44. wrap_content ● 텍스트가 긴 TextView에선 wrap_content가 의도치 않게 동작할 수 있음 ○ margin 무시됨 ○ 측정해 보면 constraint 크기가 아닌 parent 크기까지 폭이 늘어남 <TextView android:layout_width="wrap_content" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:text="asdfasdfasdlfjasdf;asdlf;jasd;flkjasdf;l..." android:layout_margin="50dp" android:maxLines="1" android:ellipsize="end" /> 44
  • 45. wrap_content ● wrap_content를 constraint 영역 내에 제대로 표현하려면 추가 설정 필요 ○ 크기는 android:layout_width="wrap_content" ○ app:layout_constrainedWidth="true" 설정을 추가 ○ 1.0.2 에선 match_constraint & layout_constraintWidth_default="wrap"  이 조합은 1.1.0 에서 deprecate됨 <TextView android:text="asdfasdfasdlfjasdf;asdlf;ja..." android:layout_width="wrap_content" app:layout_constraintedWidth="wrap" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" android:layout_margin="50dp" android:maxLines="1" android:ellipsize="end"/> 짧은 텍스트 긴 텍스트 45
  • 46. 패딩, 마진과 레이아웃의 관계 ● 부모 뷰의 패딩은 constraint 영역에서 빼야 함 ex) 300dp 폭, 좌우 패딩 50dp 이라면 constraint 영역은 300-(50)*2 = 200dp ● guideline은 부모 뷰의 패딩을 적용한 위치에 만들어짐 46
  • 47. 패딩, 마진과 레이아웃의 관계 <android.support.constraint.ConstraintLayout android:layout_width="300dp" android:layout_height="300dp" android:paddingLeft="100dp" android:paddingRight=“50dp"> <android.support.constraint.Guideline android:orientation="vertical" app:layout_constraintGuide_begin="50dp" /> → padding+begin = 100 + 50 = 150dp 위치에 생성 <android.support.constraint.Guideline android:orientation="vertical" app:layout_constraintGuide_end="50dp"/> → width - padding - end = 300- 50 - 50 = 200dp 위치에 생성 <android.support.constraint.Guideline android:orientation="vertical" app:layout_constraintGuide_percent="0.5"/> → paddingLeft + ( constraintWidth ) / 2 = 100 + ( 300- 100 - 50 ) / 2 = 100 + 75 = 175dp 위치에 생성 47
  • 48. 패딩, 마진과 레이아웃의 관계 ● 체인이 아니어도 다른 뷰와 constraint 관계를 맺을 수 있으나, 상대 뷰의 margin은 고려되지 않음 → margin까지 고려하려면 chain 관계를 가져야 함 <Button android:id="@+id/btn_a" android:layout_width="wrap_content" android:layout_marginLeft="50dp" android:layout_marginRight="50dp"/> <Button android:id="@+id/btn_b" android:layout_width="wrap_content" app:layout_cLeft_toRightOf="@id/btn_a"/>  B는 A의 marginRight를 고려하지 않음 48
  • 49. 패딩, 마진과 레이아웃의 관계 ● 다음 조건에서 자식 뷰의 왼쪽 좌표를 계산하시오 ○ 부모 뷰: 폭 300dp , 패딩 30dp ○ 자식 뷰: 폭 50dp, 좌우 마진 20dp ■ left to parent, right to parent ■ horizontal bias 0.2 ? 49
  • 50. 패딩, 마진과 레이아웃의 관계 ● view의 왼쪽 좌표 계산식 viewLeft = constraintLeft + (constraintWidth - (viewWidth+marginSide) ) * bias + marginLeft ○ constraintLeft ■ parent일 경우: parent.Left + parent.PaddingLeft ■ 특정 view A 의 오른쪽을 기준으로 할 경우: (constraintLeft_toRightOf="A" ) a.right + a.marginRight* * 둘이 packed chain style 관계일 때에만! ○ constraintWidth = constraintRight - constraintLeft ○ marginSide = marginLeft + marginRight ● viewWidth 가 constraintWidth 보다 크면 어떻게 될까? → viewLeft 가 음수가 되어 constraintLeft 보다 왼쪽에 위치할 수 있음 50
  • 51. 패딩, 마진과 레이아웃의 관계 ● 다음 조건에서 자식 뷰의 왼쪽 좌표를 계산하시오 ○ 부모 뷰: 폭 300dp , 패딩 30dp ○ 자식 뷰: 폭 50dp, 좌우 마진 20dp ■ left to parent, right to parent ■ horizontal bias 0.2 viewLeft = constraintLeft + (constraintWidth - (viewWidth+marginSide) ) * bias + marginLeft = 30 + ( 300 - 30 -30 - (50 + 20 + 20 ) ) * 0.2 + 20 = 30 + ( 240 - 90 ) * 0.2 + 20 = 30 + 30 + 20 = 80 → 50dp 위치에 barrier를 만들어서 확인해보자! 51
  • 52. 패딩, 마진과 레이아웃의 관계 <android.support.constraint.ConstraintLayout android:layout_width="300dp" android:padding="50dp"> <TextView android:layout_width="100dp"/> <TextView android:layout_width="300dp" app:layout_cHorizontal_bias="0.5"/> <TextView android:layout_width="100dp" android:layout_marginLeft="50dp"/> → constraint width = 300 - 50 - 50 = 200 viewLeft = 50 + (200 - 100) * 0.5 = 50 + 50 = 100dp → viewLeft = 50 + (200 - 300) * 0.5 = 50 - 50 = 0dp 주의: 실제로 그려질 땐 50dp 위치부터 그려지고 텍스트 앞쪽은 짤림 → padding 50dp 의 영향 → viewLeft = 50 + (200 - (100 + 50)) * 0.5 + 50 = 50 + 25 + 50 = 125dp 52
  • 53. 바라보는 뷰가 gone인 경우 - 체인 ● 사라진 뷰는 없었던 뷰 취급 ○ 뷰 크기는 0dp, 뷰의 마진도 0dp 처리 ● 체인 헤드는 사라져도 여전히 헤드 역할을 함 ○ A-B-C 체인에서 A가 gone일 경우, B가 새로운 헤더가 될까?  아니오. 여전히 A가 체인 헤더의 역할을 함 53
  • 54. 바라보는 뷰가 gone인 경우 – 비 체인 ● 사라진 뷰는 크기와 마진은 0dp인 채로 위치함 ● 사라진 뷰를 참조하던 뷰는 여전히 해당 뷰를 참조함 ○ 하지만 bias값이 있을 경우 이상하게 동작함  버그인가?? Left to parent Right to parent No bias Left to parent Right to parent Bias=0 54
  • 55. 바라보는 뷰가 gone인 경우 - layout_goneMargin ● layout_goneMargin* : 바라보는 뷰의 visibility가 gone일 때 적용되는 마진 ex) A-B-C 체인에서 ○ A가 gone 일 경우: B의 layout_goneMarginLeft가 동작 ○ C가 gone 일 경우: B의 layout_goneMarginRight가 동작 ● marginLeft와 goneMarginLeft 둘 다 적용될 상황에선 어떻게 동작할까? → goneMargin이 우선순위가 높음 ● A-B-C 체인에서 B, C 모두 layout_goneMarginLeft를 선언했고, A, B 모두 gone 된다면 B의 layout_goneMarginLeft는 동작할까? → 동작하지 않음. gone 된 뷰의 속성은 의미없음 55
  • 56. 참고자료 - ReleaseNote ● http://tools.android.com/recent/constraintlayoutbeta5isnowavailable : match_parent 크래시 위협 ● https://androidstudio.googleblog.com/2017/02/constraintlayout-10-is-now-available.html ● https://androidstudio.googleblog.com/2017/03/constraintlayout-101-is-now-available.html ● https://androidstudio.googleblog.com/2017/03/constraintlayout-102-is-now-available.html ● https://androidstudio.googleblog.com/2017/05/constraintlayout-110-beta-1-release.html ● https://androidstudio.googleblog.com/2017/10/constraintlayout-110-beta-2.html . packed chain의 0dp, 이 버전부턴 match_constraint로 동작함 . app:layout_constrainedWidth="true|false" 추가 ● https://androidstudio.googleblog.com/2017/10/constraintlayout-110-beta-3-is-now.html . Circular constraints 추가 ● https://androidstudio.googleblog.com/2017/12/constraintlayout-110-beta-4.html ● https://androidstudio.googleblog.com/2018/02/constraintlayout-110-beta-5.html ● https://androidstudio.googleblog.com/2018/03/constraintlayout-110-beta-6.html ● https://androidstudio.googleblog.com/2018/04/constraintlayout-110.html 56
  • 57. 참고자료 - 구글 자료 ● https://android-developers.googleblog.com/2017/08/understanding- performance-benefits-of.html ● https://www.youtube.com/watch?list=PLWz5rJ2EKKc9e0d55YHgJFHXNZbGH EXJX&time_continue=1&v=OHcfs6rStRo ● https://developer.android.com/reference/android/support/constraint/Constr aintLayout.html ● https://developer.android.com/training/constraint-layout/index.html ● https://codelabs.developers.google.com/codelabs/constraint-layout/#0 57
  • 58. 참고자료 - 기타 ● https://constraintlayout.com/ ● https://academy.realm.io/posts/360-andev-2017-nicolas-roard-advanced- constraintlayout/ ● https://academy.realm.io/kr/posts/constraintlayout-it-can-do-what-now/ ● https://proandroiddev.com/creating-awesome-animations-using-constraintlayout- and-constraintset-part-i-390cc72c5f75 ● https://medium.com/@rafael_toledo/whats-new-in-constraint-layout-1-1-x- f0bdd4dbdfb3 ● http://androidkt.com/constraintlayout/ ● https://gist.github.com/kingori/fa4a71bf4e844b02d772d8c6d667fd32#file- constraintlayout-xml ● https://github.com/kingori/Droidknight_ConstraintLayout 58
  • 59. Q & A
  • 60.