SlideShare une entreprise Scribd logo
1  sur  60
Télécharger pour lire hors ligne
지금은 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
끝

Contenu connexe

Tendances

신입 SW 개발자 취업 준비
신입 SW 개발자 취업 준비신입 SW 개발자 취업 준비
신입 SW 개발자 취업 준비인서 박
 
Google I/O 2011, Android Accelerated Rendering
Google I/O 2011, Android Accelerated RenderingGoogle I/O 2011, Android Accelerated Rendering
Google I/O 2011, Android Accelerated RenderingRomain Guy
 
Understaing Android EGL
Understaing Android EGLUnderstaing Android EGL
Understaing Android EGLSuhan Lee
 
SOLID : les principes à l’origine du succès de Symfony et de vos applications
SOLID : les principes à l’origine du succès de Symfony et de vos applicationsSOLID : les principes à l’origine du succès de Symfony et de vos applications
SOLID : les principes à l’origine du succès de Symfony et de vos applicationsVladyslav Riabchenko
 
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기Jaeseung Ha
 
Introduction to React Native Workshop
Introduction to React Native WorkshopIntroduction to React Native Workshop
Introduction to React Native WorkshopIgnacio Martín
 
Inter Process Communication (IPC) in Android
Inter Process Communication (IPC) in AndroidInter Process Communication (IPC) in Android
Inter Process Communication (IPC) in AndroidMalwinder Singh
 
심성환 개발자 포트폴리오
심성환 개발자 포트폴리오심성환 개발자 포트폴리오
심성환 개발자 포트폴리오Seonghwan Shim
 
JavaScript Event Loop
JavaScript Event LoopJavaScript Event Loop
JavaScript Event LoopDesignveloper
 
Introduction to Node js
Introduction to Node jsIntroduction to Node js
Introduction to Node jsAkshay Mathur
 
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서Jeongmin Cha
 
NDC2017 언리얼 엔진4 애니메이션 공유 캐릭터 설계
NDC2017 언리얼 엔진4 애니메이션 공유 캐릭터 설계NDC2017 언리얼 엔진4 애니메이션 공유 캐릭터 설계
NDC2017 언리얼 엔진4 애니메이션 공유 캐릭터 설계언호 이
 
[부스트캠프 웹・모바일 7기 Tech Talk]박명범_RecyclerView는 어떻게 재활용하는가
[부스트캠프 웹・모바일 7기 Tech Talk]박명범_RecyclerView는  어떻게  재활용하는가[부스트캠프 웹・모바일 7기 Tech Talk]박명범_RecyclerView는  어떻게  재활용하는가
[부스트캠프 웹・모바일 7기 Tech Talk]박명범_RecyclerView는 어떻게 재활용하는가CONNECT FOUNDATION
 
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드NAVER Engineering
 
DirectStroage프로그래밍소개
DirectStroage프로그래밍소개DirectStroage프로그래밍소개
DirectStroage프로그래밍소개YEONG-CHEON YOU
 

Tendances (20)

신입 SW 개발자 취업 준비
신입 SW 개발자 취업 준비신입 SW 개발자 취업 준비
신입 SW 개발자 취업 준비
 
Google I/O 2011, Android Accelerated Rendering
Google I/O 2011, Android Accelerated RenderingGoogle I/O 2011, Android Accelerated Rendering
Google I/O 2011, Android Accelerated Rendering
 
Understaing Android EGL
Understaing Android EGLUnderstaing Android EGL
Understaing Android EGL
 
SOLID : les principes à l’origine du succès de Symfony et de vos applications
SOLID : les principes à l’origine du succès de Symfony et de vos applicationsSOLID : les principes à l’origine du succès de Symfony et de vos applications
SOLID : les principes à l’origine du succès de Symfony et de vos applications
 
Git in action
Git in actionGit in action
Git in action
 
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
NDC 2017 하재승 NEXON ZERO (넥슨 제로) 점검없이 실시간으로 코드 수정 및 게임 정보 수집하기
 
Introduction to React Native Workshop
Introduction to React Native WorkshopIntroduction to React Native Workshop
Introduction to React Native Workshop
 
Inter Process Communication (IPC) in Android
Inter Process Communication (IPC) in AndroidInter Process Communication (IPC) in Android
Inter Process Communication (IPC) in Android
 
심성환 개발자 포트폴리오
심성환 개발자 포트폴리오심성환 개발자 포트폴리오
심성환 개발자 포트폴리오
 
Modular Monoliths with Nx
Modular Monoliths with NxModular Monoliths with Nx
Modular Monoliths with Nx
 
JavaScript Event Loop
JavaScript Event LoopJavaScript Event Loop
JavaScript Event Loop
 
Introduction to Node js
Introduction to Node jsIntroduction to Node js
Introduction to Node js
 
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
 
NDC2017 언리얼 엔진4 애니메이션 공유 캐릭터 설계
NDC2017 언리얼 엔진4 애니메이션 공유 캐릭터 설계NDC2017 언리얼 엔진4 애니메이션 공유 캐릭터 설계
NDC2017 언리얼 엔진4 애니메이션 공유 캐릭터 설계
 
[부스트캠프 웹・모바일 7기 Tech Talk]박명범_RecyclerView는 어떻게 재활용하는가
[부스트캠프 웹・모바일 7기 Tech Talk]박명범_RecyclerView는  어떻게  재활용하는가[부스트캠프 웹・모바일 7기 Tech Talk]박명범_RecyclerView는  어떻게  재활용하는가
[부스트캠프 웹・모바일 7기 Tech Talk]박명범_RecyclerView는 어떻게 재활용하는가
 
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
 
Google closure compiler
Google closure compilerGoogle closure compiler
Google closure compiler
 
Reactjs
ReactjsReactjs
Reactjs
 
Introdução Vue JS
Introdução Vue JSIntrodução Vue JS
Introdução Vue JS
 
DirectStroage프로그래밍소개
DirectStroage프로그래밍소개DirectStroage프로그래밍소개
DirectStroage프로그래밍소개
 

Plus de Sewon Ann

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

Plus de Sewon Ann (9)

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

지금은 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.