HOME > android > basic

안드로이드 - ConstraintLayout 구현 방법

By JS | 16 Sep 2017

ConstraintLayout

ConstraintLayout는 유연하게 다른 View들을 배치할 수 있는 ViewGroup입니다. 이 Layout은 Android SDK에 포함되어있지 않기 때문에 Android Support Library로 API Level 9(Gingerbread)부터 지원을 하고 있습니다. 사용하려면 Android Support Library를 gradle에서 load를 해야 합니다.

Constraint(제약) Layout의 기본 개념은 말 그대로 객체간에 제약(제한) 조건을 설정함으로써 배치를 하는 것입니다. 예를들어 A와 B 객체간에 제약 조건을 설정하여 두 객체가 붙어있거나 떨어져 있거나 등 배치를 할 수 있습니다.

ConstraintLayout은 RelativeLayout과 유사한 점이 있습니다. 하지만 성능 측면에서 RelativeLayout과 동일하거나 더 빠르다고 합니다.

Android Studio에서는 Layout Editor Tool을 지원하여 Code로 UI를 개발하지 않고 Tool로 간단히 개발할 수 있다고 합니다. 자세한 내용은 Layout Editor로 UI 디자인하기: Android Studio UserGuide에서 확인해주세요.

지금부터 예제와 함께 ConstraintLayout에 대해서 자세히 알아보겠습니다.

프로젝트 생성하기

[File] >> [New] >> [New Project]에서 Empty Activity를 선택하시고 새 프로젝트를 생성해주세요.

프로젝트를 생성하면 자동적으로 MainActivity.java와 activity_main.xml 파일이 생성됩니다. MainActivity.java 코드를 보면 activity_main.xml으로 UI Layout을 정의하도록 코드가 입력되어있습니다.

ConstraintLayout을 사용하려면 gradle에서 Android Support library를 사용하겠다고 정의해야합니다. Android Studio에서 app/build.gradle을 열고 dependencies에 아래처럼 com.android.support.constraint:constraint-layout:1.0.2을 추가해주세요. 프로젝트를 생성할 때 기본적으로 추가되어 있는데 만약 없다면 추가해주시면 됩니다.

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'
}

상대적인 배치(Relative Positioning)

이 부분은 RelativeLayout과 유사합니다. Constraint layout도 내부의 객체를 배치할 때 부모 또는 자식 객체들 간의 상대적인 위치로 배치 할 수 있습니다.

위에서 말씀드린 것 처럼 기본 개념은 Constraint(제약, 제한) 조건입니다. 객체의 4개의 면을 다른 객체의 특정 면에 제약 조건을 설정하여 상대적인 위치를 지정해줄 수 있습니다.

예를들어 이 객체의 왼쪽 라인을 어떤 객체의 왼쪽 라인과 동일한 라인에 정렬하도록 할 수 있습니다. 마치 끈으로 두 면을 묶었다고(제약 조건) 생각하시면 이해하기 쉬울 수 있습니다.

RelativeLayout과 다른 점으로는 부모와 자식객체 모두 동일 속성을 사용하여 상대적인 배치를 할 수 있다는 것과, 부모 중앙에 배치하는 속성이 없어졌다는 것입니다. 부모의 중앙에 배치하는 것은 다른 부분으로 지원하고 있고 이 부분은 중앙 배치(Centering positioning)에서 알아보겠습니다.

아래 속성들을 이용하여 객체간의 Constraint(제약) 조건을 설정하여 상대적인 배치를 할 수 있습니다.

XML attributes
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 Baseline을 어떤 객체의 Baseline에 배치

예제를 통해 Constraint(제약) 조건을 설정 방법과 상대적인 위치를 설정하는 방법을 알아보겠습니다. 아래 코드를 입력하시고 결과를 확인해주세요.

ConstraintLayout의 속성을 사용하려면 ConstraintLayout 속성에 xmlns:app="http://schemas.android.com/apk/res-auto"을 정의해야 합니다.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.codestudio.myapplication.MainActivity">

    <TextView
        android:id="@+id/tv01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView01"
        android:padding="5dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        android:background="#81c784"/>

    <TextView
        android:id="@+id/tv02"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView02"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@id/tv01"
        app:layout_constraintLeft_toLeftOf="parent"
        android:background="#e0e0e0"/>

    <TextView
        android:id="@+id/tv03"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView03"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@id/tv02"
        app:layout_constraintLeft_toRightOf="@id/tv02"
        android:background="#ff8a65"/>

    <TextView
        android:id="@+id/tv04"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView04"
        android:padding="5dp"
        app:layout_constraintBottom_toTopOf="@id/tv03"
        app:layout_constraintLeft_toRightOf="@id/tv03"
        android:background="#c2c500"/>

</android.support.constraint.ConstraintLayout>

TextView01은 layout_constraintTop_toTopOf="parent" 와 layout_constraintLeft_toLeftOf="parent"의 제한(Constraint) 조건을 설정하였습니다. parent는 부모 객체인 ConstraintLayout을 말합니다. TextView01의 위쪽 면은 부모 객체의 위쪽 면과 동일한 라인에 위치하도록 제한 조건을 설정하였습니다. 그리고 왼쪽 면은 부모의 왼쪽면과 동일한 라인에 위치하도록 하였습니다. 결과를 보시면 TextView01은 부모의 왼쪽 위쪽 라인과 동일 선상에 배치되었습니다.

TextView02는 상단을 TextView01 하단에, 좌측을 부모 좌측에 제약조건을 설정하였습니다.

TextView03은 상단을 TextView02 하단에, 좌측을 TextView2 우측에 제약조건을 설정하였습니다.

TextView04는 하단을 TextView03 상단에, 좌측을 TextView3 우측에 제약조건을 설정하였습니다.

결과를 보면 제약조건처럼 상대적인 위치가 설정되었습니다. ConstarintLayout도 RelativeLayout처럼 기본적으로 설정하지 않으면 왼쪽, 위쪽으로 View가 배치됩니다. 일반적으로 가로축과 세로축 두개의 제약조건을 설정하면 의도한 대로 View를 배치할 수 있습니다.

constraintlayout

중앙 배치(Centering positioning)

Costraint의 기본 개념은 객체에 제약 조건을 설정하여 배치를 하는 것입니다. 위의 상대적인 배치에서는 가로축, 세로축의 한쪽 면만 제약 조건을 걸었는데요. 양쪽 면에 제약조건을 걸면 객체가 중앙에 배치됩니다.

상대적인 배치에서 배운 속성들을 모두 공통적으로 사용하고, 추가로 알아햘 것은 bias 속성입니다.

XML attributes
layout_constraintHorizontal_bias 가로축에서 객체의 치우친 정도를 설정
layout_constraintVertical_bias 세로축에서 객체의 치우친 정도를 설정

예제를 통해서 자세히 알아보겠습니다. 아래 코드를 입력하시고 결과를 확인해주세요.

코드를 보면 TextView가 3개 있고 각각 좌측, 우측 면에 제약 조건을 설정했습니다. 위쪽 면은 겹치지 않도록 상대적인 위치를 설정하였습니다.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.codestudio.myapplication.MainActivity">

    <TextView
        android:id="@+id/tv01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView01"
        android:padding="5dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:background="#81c784"/>

    <TextView
        android:id="@+id/tv02"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView02"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@id/tv01"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintHorizontal_bias="0.2"
        android:background="#e0e0e0"/>

    <TextView
        android:id="@+id/tv03"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView03"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@id/tv02"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintHorizontal_bias="0.8"
        android:background="#ff8a65"/>

</android.support.constraint.ConstraintLayout>

TextView01은 layout_constraintLeft_toLeftOf="parent"layout_constraintRight_toRightOf="parent"로 설정되었습니다. 좌측면은 부모의 좌측면에, 우측면은 부모의 우측면과 동일 라인에 배치되도록 제한 조건을 설정하였습니다. 이렇게 설정할 경우 TextView01은 부모의 중앙에 배치됩니다. 객체의 양쪽면이 부모와 끈으로 연결되어있고, 같은 힘으로 당겨 가운데 위치하게 된 것 같습니다.

TextView02도 TextView01처럼 양쪽면을 부모의 양쪽면으로 제한조건을 설정했습니다. 중앙에 배치되어야 하지만 layout_constraintHorizontal_bias="0.2" 으로 객체가 왼쪽으로 치우치게 배치되었습니다. 0.2의 의미는 여백 중에 객체 왼쪽의 여백이 20%가 되고 오른쪽이 80%가 되도록 설정하겠다는 의미입니다. 만약 0.5로 설정한다면 정 중앙에 배치됩니다.

TextView03은 layout_constraintHorizontal_bias="0.8"로 설정되었습니다. 왼쪽 여백이 80%를 차지하도록 배치되었습니다.

constraintlayout

Android Studio의 Preview에서 TextView02 객체를 클릭해보세요. 클릭하면 그림처럼 제약조건이 선으로 시각화하여 보여줍니다. TextView02는 상단 면이 TextView02의 하단 면에 연결되어있고, 양쪽면은 부모의 양쪽면에 연결되었습니다.

constraintlayout

마진(Margin)

마진이 설정되면 제약조건 방향으로 마진을 적용합니다. 만약 A객체의 좌측면을 부모의 좌측면에 제약조건을 설정하였고 왼쪽으로 마진을 10dp만큼 설정하면, 부모의 좌측면과 객체의 좌측면 사이에 마진을 10dp만큼 적용합니다. 제약조건 사이의 마진이기 때문에 제약조건이 없으면 마진이 적용되지 않습니다.

마진과 관련된 속성은 아래와 같습니다.

XML attributes
layout_marginLeft 좌측 제약조건 사이에 마진 적용
layout_marginTop 상단 제약조건 사이에 마진 적용
layout_marginRight 우측 제약조건 사이에 마진 적용
layout_marginBottom 하단 제약조건 사이에 마진 적용

예제로 자세히 알아보겠습니다.

코드를 보면 제약조건이 설정되었고 그 방향으로 마진이 설정되었습니다.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.codestudio.myapplication.MainActivity">

    <TextView
        android:id="@+id/tv01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView01"
        android:padding="5dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="10dp"
        android:background="#81c784"/>

    <TextView
        android:id="@+id/tv02"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView02"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@id/tv01"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginTop="20dp"
        android:layout_marginLeft="20dp"
        android:background="#e0e0e0"/>

    <TextView
        android:id="@+id/tv03"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView03"
        android:padding="5dp"
        android:layout_marginTop="30dp"
        android:layout_marginLeft="30dp"
        app:layout_constraintTop_toBottomOf="@id/tv02"
        app:layout_constraintLeft_toLeftOf="parent"
        android:background="#ff8a65"/>


</android.support.constraint.ConstraintLayout>

TextView01은 상단과 좌측면에 제약조건이 설정되었고 그 방향으로 10dp만큼 마진이 적용되었습니다.

TextView02는 제약조건 방향으로 20dp만큼, TextView03은 30dp만큼 설정되었습니다.

제약조건이 없으면 마진이 적용되지 않는지 직접 코드를 수정하고 확인해보세요.

constraintlayout

체인(Chain)

체인은 가로 또는 세로 축의 방향으로 객체들을 서로서로 묶는 것을 말합니다. 아래 그림처럼 제한조건을 이용해 부모의 끝부터 끝까지 객체들을 연결합니다.

constraintlayout

체인은 그룹같은 속성을 갖고 있으며, 체인의 맨 첫번째 객체를 Head라고 합니다. constraintlayout

체인 스타일을 설정할 수도 있습니다. 스타일은 아래와 같은 종류가 있습니다. constraintlayout

체인에서 사용되는 새로운 속성들입니다.

XML attributes
layout_constraintHorizontal_chainStyle 가로축 체인의 스타일을 설정
layout_constraintVertical_chainStyle 세로축 체인의 스타일을 설정
layout_constraintHorizontal_weight 가로축 체인의 weight
layout_constraintVertical_weight 세로축 체인의 weight

예제로 자세히 알아보겠습니다. 아래 코드를 입력하시고 결과를 확인해주세요.

코드를 보면 TextView01, 02, 03이 체인으로 묶여있고, TextView04, 05, 06이 체인으로 묶여있습니다.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.codestudio.myapplication.MainActivity">


    <TextView
        android:id="@+id/tv01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView01"
        android:padding="5dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/tv02"
        app:layout_constraintHorizontal_chainStyle="spread"
        android:background="#81c784"/>

    <TextView
        android:id="@+id/tv02"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView02"
        android:padding="5dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/tv01"
        app:layout_constraintRight_toLeftOf="@+id/tv03"
        android:background="#e0e0e0"/>

    <TextView
        android:id="@+id/tv03"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView03"
        android:padding="5dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/tv02"
        app:layout_constraintRight_toRightOf="parent"
        android:background="#ff8a65"/>

    <TextView
        android:id="@+id/tv04"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView04"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@+id/tv01"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/tv05"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        android:background="#81c784"/>

    <TextView
        android:id="@+id/tv05"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView05"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@+id/tv01"
        app:layout_constraintLeft_toRightOf="@+id/tv04"
        app:layout_constraintRight_toLeftOf="@+id/tv06"
        android:background="#e0e0e0"/>

    <TextView
        android:id="@+id/tv06"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView06"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@+id/tv01"
        app:layout_constraintLeft_toRightOf="@+id/tv05"
        app:layout_constraintRight_toRightOf="parent"
        android:background="#ff8a65"/>

</android.support.constraint.ConstraintLayout>

Spread Chain

TextView01, 02, 03 체인의 Head는 TextView01입니다. 체인 스타일은 Head 객체의 속성으로 설정이 가능합니다. layout_constraintHorizontal_chainStyle="spread"로 Spread 스타일로 설정하였습니다. Spread 체인스타일은 객체들을 동일 간격으로 배치합니다. 만약 스타일을 설정하지 않으면 Spread 스타일이 기본으로 적용됩니다.

Spread Inside Chain

TextView04, 05, 06 체인의 Head는 TextView04입니다. 이 체인의 스타일은 spread_inside로 설정하였습니다. Spread Inside 스타일은 양쪽 객체가 부모 끝에 붙고 동일 간격으로 객체를 배치합니다.

constraintlayout

다른 스타일을 확인해보겠습니다. 다음 코드를 입력하시고 결과를 확인해주세요.

코드를 보면 3개의 체인그룹이 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.codestudio.myapplication.MainActivity">


    <TextView
        android:id="@+id/tv01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView01"
        android:padding="5dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/tv02"
        app:layout_constraintHorizontal_chainStyle="packed"
        android:background="#81c784"/>

    <TextView
        android:id="@+id/tv02"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView02"
        android:padding="5dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/tv01"
        app:layout_constraintRight_toLeftOf="@+id/tv03"
        android:background="#e0e0e0"/>

    <TextView
        android:id="@+id/tv03"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView03"
        android:padding="5dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/tv02"
        app:layout_constraintRight_toRightOf="parent"
        android:background="#ff8a65"/>

    <TextView
        android:id="@+id/tv04"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView04"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@+id/tv01"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/tv05"
        app:layout_constraintHorizontal_bias="0.2"
        app:layout_constraintHorizontal_chainStyle="packed"
        android:background="#81c784"/>

    <TextView
        android:id="@+id/tv05"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView05"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@+id/tv01"
        app:layout_constraintLeft_toRightOf="@+id/tv04"
        app:layout_constraintRight_toLeftOf="@+id/tv06"
        android:background="#e0e0e0"/>

    <TextView
        android:id="@+id/tv06"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView06"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@+id/tv01"
        app:layout_constraintLeft_toRightOf="@+id/tv05"
        app:layout_constraintRight_toRightOf="parent"
        android:background="#ff8a65"/>

    <TextView
        android:id="@+id/tv07"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView07"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@+id/tv04"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/tv08"
        app:layout_constraintHorizontal_bias="0.8"
        app:layout_constraintHorizontal_chainStyle="packed"
        android:background="#81c784"/>

    <TextView
        android:id="@+id/tv08"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView08"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@+id/tv04"
        app:layout_constraintLeft_toRightOf="@+id/tv07"
        app:layout_constraintRight_toLeftOf="@+id/tv09"
        android:background="#e0e0e0"/>

    <TextView
        android:id="@+id/tv09"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView09"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@+id/tv04"
        app:layout_constraintLeft_toRightOf="@+id/tv08"
        app:layout_constraintRight_toRightOf="parent"
        android:background="#ff8a65"/>
</android.support.constraint.ConstraintLayout>

Packed Chain

TextView01, 02, 03 체인은 packed 체인으로 설정되었습니다. Packed 체인은 객체끼리 붙어있고 가운데로 정렬되어있습니다.

Packed Chain with Bias

이 스타일은 Packed 체인과 동일한데 Bias로 치우침 정도를 조절할 수 있습니다. 지금까지 배운 bias와 같이 layout_constraintHorizontal_bias로 설정할 수 있습니다.

TextView04, 05, 06은 bias를 0.2로 설정하였고 왼쪽 여백을 20%로 설정하였습니다.

TextView07, 08, 09은 bias를 0.8로 설정하였고 왼쪽 여백을 80%로 설정하였습니다.

constraintlayout

다른 스타일을 확인해보겠습니다. 다음 코드를 입력하시고 결과를 확인해주세요.

코드를 보면 3개의 체인그룹이 있습니다.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.codestudio.myapplication.MainActivity">


    <TextView
        android:id="@+id/tv01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView01"
        android:padding="5dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/tv02"
        app:layout_constraintHorizontal_chainStyle="spread"
        android:background="#81c784"/>

    <TextView
        android:id="@+id/tv02"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="TextView02"
        android:padding="5dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@id/tv01"
        app:layout_constraintRight_toLeftOf="@id/tv03"
        android:background="#e0e0e0"/>

    <TextView
        android:id="@+id/tv03"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView03"
        android:padding="5dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@id/tv02"
        app:layout_constraintRight_toRightOf="parent"
        android:background="#ff8a65"/>

    <TextView
        android:id="@+id/tv04"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView04"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@id/tv01"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/tv05"
        app:layout_constraintHorizontal_chainStyle="spread"
        android:background="#81c784"/>

    <TextView
        android:id="@+id/tv05"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="TextView05"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@id/tv01"
        app:layout_constraintLeft_toRightOf="@id/tv04"
        app:layout_constraintRight_toLeftOf="@id/tv06"
        android:background="#e0e0e0"/>

    <TextView
        android:id="@+id/tv06"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="TextView06"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@id/tv01"
        app:layout_constraintLeft_toRightOf="@id/tv05"
        app:layout_constraintRight_toRightOf="parent"
        android:background="#ff8a65"/>

    <TextView
        android:id="@+id/tv07"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView07"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@id/tv04"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@id/tv08"
        app:layout_constraintHorizontal_chainStyle="spread"
        android:background="#81c784"/>

    <TextView
        android:id="@+id/tv08"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="TextView08"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@id/tv04"
        app:layout_constraintLeft_toRightOf="@id/tv07"
        app:layout_constraintRight_toLeftOf="@id/tv09"
        app:layout_constraintHorizontal_weight="0.6"
        android:background="#e0e0e0"/>

    <TextView
        android:id="@+id/tv09"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="TextView09"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@id/tv04"
        app:layout_constraintLeft_toRightOf="@id/tv08"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintHorizontal_weight="0.4"
        android:background="#ff8a65"/>

</android.support.constraint.ConstraintLayout>

Weighted Chain

Weighted Chain 스타일로 설정하는 방법은 Head의 스타일을 Spread로 설정하고, 어떤 체인 객체의 Width를 0dp로 설정하면 됩니다. 이 스타일은 Spread Inside 스타일에서 width를 0dp로 설정한 객체가 빈 공간을 차지하게 합니다. (Horizontal은 Width를 0dp로, Vertical은 Height를 0dp로 설정해야합니다.)

TextView01, 02, 03 체인은 Weighted Chain 스타일로 설정되었습니다. TextView02의 width만 0dp이기 때문에 남은 공간은 모두 TextView02에게 할당되었습니다.

TextView04, 05, 06 체인도 Weighted Chain 스타일로 설정되었고, 05와 06의 width가 0dp로 설정되었습니다. 그래서 남은 공간은 05와 06이 사이좋게 나누어 가졌습니다.

TextView07, 08, 09 체인도 위의 체인과 거의 동일합니다. 하지만 여기서는 08과 09가 사이좋게 나누어 갖지 않고 layout_constraintHorizontal_weight 속성으로 비율을 정했습니다. TextView08은 0.6을 설정하였고 TextView09는 0.4를 설정하였습니다. 지금까지 배운 것처럼 TextView08은 60%를 가져가고 TextView09가 40%를 가져갔습니다.

constraintlayout

면적 제약(Dimension constraint)

Dimension은 면적, 크기 등을 의미합니다. android:minWidth 또는 android:minHeight 등으로 최소 너비, 높이 등을 제한할 수 있습니다. 또한 width, height의 비율도 설정할 수 있습니다.

예제로 비율에 대해서 알아보겠습니다. 다음 코드를 입력하시고 결과를 확인해주세요.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.codestudio.myapplication.MainActivity">

    <TextView
        android:id="@+id/tv01"
        android:layout_width="100dp"
        android:layout_height="0dp"
        android:text="TextView01"
        android:padding="5dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintDimensionRatio="2:1"
        android:background="#81c784"/>

    <TextView
        android:id="@+id/tv02"
        android:layout_width="100dp"
        android:layout_height="0dp"
        android:text="TextView02"
        android:padding="5dp"
        app:layout_constraintTop_toBottomOf="@id/tv01"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintDimensionRatio="1:2"
        android:background="#e0e0e0"/>

</android.support.constraint.ConstraintLayout>

Dimension을 설정하려면 한쪽 길이의 크기를 0dp로 설정하고 layout_constraintDimensionRatio로 비율을 설정해야 합니다.

TextView01의 경우 width 100dp, height를 0dp, layout_constraintDimensionRatio="2:1"로 설정하였습니다. 가로:세로 비율을 의미하고 그래서 높이가 50dp로 설정되었습니다.

TextView02의 경우 width 100dp, height를 0dp, 비율은 "1:2"로 설정하여 높이가 200dp로 설정되었습니다.

constraintlayout

정리

ConstraintLayout의 가장 기본적인 것에 대해서 살펴보았습니다. 좀 더 자세한 내용은 Android API Reference를 참조해주세요.

튜토리얼에서 사용한 코드는 GitHub: ConstraintLayout에서 확인하실 수 있습니다.

참고