ConstraintLayout

LinearLayount에 이어서 이번에는 ConstraintLayout에 대해 글을 작성해 보겠다.

Flutter에도 Constraints 위젯이 있는데, 같은 기능이라고 보면된다. 저는 Constraints 관련 위젯은 잘 사용하지 않습니다.

Native 앱 개발시에도 Flutter 개발 정도 까지는 아니지만, 안드로이드 디바이스의 크기가 제각각이기 때문에 뷰의 사이즈를 잘 만들어 주어야 한다.
Flutter에서는 IOS까지 사이즈를 고려해야 하기에 주로 앱 개발시 전역에서 사용할 사이즈 관련 로직을 만들어서 앱 실행시 디바이스 사이즈에 맞게 비율로 계산되는 로직을 넣어서 사용을 해왔다. 현재 안드로이드 디바이스는 최근 리사이즈 디바이스가 나오면서 조금 신경쓸게 많아지긴 했는데, IOS는 작은건 진짜 작다.. SE 1세대는 정말 작아요.. ㅠㅠ

서론이 길었는데, ConstraintLayout의 이름에서 알 수 있듯이 사이즈의 제약 조건을 따르는 Layout이라는 생각이 든다.
다른 강의나 글을 찾아보면 디바이스 사이즈의 다양성으로 인하여 LinearLayout보다는 ConstraintLayout을 더 많이 쓴다고 한다.

ConstraintLayout을 가볍게 파악해보자.

xml (ConstraintLayout)

안드로이드 프로젝트를 생성하면 초기 activity_main.xml 파일의 기본 코드가 아래와 같이 생성되어 있는데, 기본 코드에서도 Constraintlayout을 사용한다는 것을 알 수 있다.
디자인 탭의 레이아웃 뷰를 보면 연결선이 나와있는데, 연결선의 제약조건안에 자식 뷰가 위치한다고 보면된다.

Constraintlayout도 layout이기에 Linearlayout처럼 뷰 전체 영역을 차지하려면 width, height를 match_parent로 해주고, 자식 뷰의 크기만큼만 사이즈를 줄 때는 wrap_content로 해주면 된다.

아래 TextView의 app:layout 속성이 Linearlayout과 Constraintlayout의 차이라고 볼 수 있다. Linearlayout의 weight와 비슷해보이지만 사용해보니 확실히 다른 기능이다.

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

아래 코드는 세 개의 ConstraintLayout을 사용해서 각각 디바이스 높이의 20% / 25% / 55%, 가로 폭은 모두 100% 영역을 차지하게 layout 구조를 만드는 방법이다.

디자인 탭의 레이아웃 구조를 보면 layout 테두리에 파란색 점과 흰색 점이 있는데, Constraintlayout 연결선이 부모 Constraintlayout의 제약이다.

<androidx.constraintlayout.widget.ConstraintLayout 
	...>
                                                   
<androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/top"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@color/teal_200"
        app:layout_constraintHeight_percent="0.2"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintWidth_percent="1" />

<androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/middle"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@color/teal_700"
        app:layout_constraintHeight_percent="0.25"
        app:layout_constraintWidth_percent="1"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/top" />

<androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@color/purple_500"
        app:layout_constraintHeight_percent="0.55"
        app:layout_constraintWidth_percent="1"
        app:layout_constraintTop_toBottomOf="@+id/middle"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

가장 최상단에 배치되는 layout 코드이다. id 값은 top으로 주었고, 배경 색상은 teal_200으로 해주었다. width와 height 값을 0dp로 해주어야 Constrintlayout의 부모 제약조건을 가지게 된다.
layout_constraintHeight_percent, layout_constraintWidth_percent의 속성은 자식 뷰의 값을 합친게 1을 초과하면 안된다. 전체 사이즈가 1이기에 자식 뷰의 비율이 되는 값을 넣어주면 된다.

Top_toTopOf, Start_toStartOf, End_toEndOf, Bottom_toBottomOf 속성 값으로 뷰의 위치와 사이즈를 결정하게 된다.

해당 조건은 Top, Start, End 제약은 부모의 연결선으로 지정한 것이다.

<androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/top"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@color/teal_200"
        app:layout_constraintHeight_percent="0.2"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintWidth_percent="1" />

중간에 배치되는 레이아웃에서 다른 점을 보면 최상단에 배치한 레이아웃의 id 값을 Top_toBottomOf의 값으로 넣어줌에 따라 상단 뷰의 바로 아래에 위치할 수 있게 된다.

<androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/middle"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@color/teal_700"
        app:layout_constraintHeight_percent="0.25"
        app:layout_constraintWidth_percent="1"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/top" />

마지막에 위치하는 레이아웃이다.

<androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@color/purple_500"
        app:layout_constraintHeight_percent="0.55"
        app:layout_constraintWidth_percent="1"
        app:layout_constraintTop_toBottomOf="@+id/middle"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

app:layout_constraint 값에서 Top은 좌측, End는 우측, Top과 Bottom은 상단, 하단을 나타내는 것이다.

마무리

직접 앱을 만들어보면서 UI 구현을 통해서 좀 더 깊게 사용해보고 할 수 있는데, 간단하게 글을 올리기 위해 사용하다 보니 실제 layout을 잡고 반응형으로 사이즈를 만들 때도 저렇게 사용해야 하나 의문이 들기는하다.

하루 빨리 네이티브로 간단한 앱이라도 개발해서 개발 과정을 블로그 글의 예제로 써봐야 할 것 같다.

profile
Flutter Developer

0개의 댓글