정답보다 해답을

[Android] ConstraintLayout 알고 쓰자. 본문

Android

[Android] ConstraintLayout 알고 쓰자.

DOLMENG. 2024. 10. 28. 22:47
📑 목차
ConstraintLayout이란?
ConstraintLayout의 장점
기본 사용법
제약 조건 유형체인(Chains) 활용하기
주요 속성 정리

 

ConstraintLayout을 알기 전에는 LinearLayout을 주로 사용해왔다. 다른 이유는 없고 편해서

하지만 화면이 복잡해질수록 레이아웃을 중첩해서 써야하는 경우가 많기 때문에 오히려 불편한 상황이 생겼다.

ConstraintLayout의 사용법과 활용하면서 유용했던 부분을 중점적으로 작성해보려고 한다.

 

1. ConstraintLayout이란?

ConstraintLayout은 안드로이드에서 복잡한 UI 레이아웃을 효과적으로 구성하기 위한 레이아웃이다.

기존의 RelativeLayout, LinearLayout 등을 대체하여 더 유연하게 UI를 배치할 수 있게 합니다.

ConstraintLayout은 Android API 9 레벨부터 지원되는 레이아웃 라이브러리이다.

 

상하좌우에 제약조건을 걸어 View를 배치하는 기법이다.

최소 2개의 제약조건을 걸어줘야한다. 아니면 조건이 부족하다고 나온다.
Bottom, End, Start, Top을 기준으로 배치한다.

줄이면 BEST가 된다.

위 사진은 수지와 짱구가 양쪽에서 흰둥이를 당기고 있는 모습이다.

이를 Constraint 관점에서 보면 현재 흰둥이는 다음과 같은 상태라고 볼 수 있다.

이번 포스팅에서는 수지, 흰둥이, 짱구의 관계로 ConstraintLayout을 공부해보자.

app:layout_constraintEnd_toStartOf="parent"
app:layout_constraintStart_toEndOf="parent"

 

2. ConstraintLayout의 장점

 

  • 단일 레이아웃으로 복잡한 UI를 표현 가능 -> 다른 레이아웃과는 다르게 중첩하며 사용하지 않아도 된다.
  • 성능 최적화: 중첩 레이아웃을 줄여 성능 향상
  • 다양한 제약 조건을 통해 구성 요소 간 관계를 쉽게 설정
  • 레퍼런스 ID 사용으로 명확한 레이아웃 구조 표현 -> 제약조건을 걸어주려면 반드시 ID를 명시해야한다.

 

3. 기본 사용법

layout_constraintTop_toTopOf 뷰의 위쪽 사이드(Side)를 대상 뷰의 위쪽 사이드(Side)에 맞춤.
layout_constraintTop_toBottomOf 뷰의 위쪽 사이드(Side)를 대상 뷰의 아래쪽 사이드(Side)에 맞춤.
layout_constraintBottom_toTopOf 뷰의 아래쪽 사이드(Side)를 대상 뷰의 위쪽 사이드(Side)에 맞춤.
layout_constraintBottom_toBottomOf 뷰의 아래쪽 사이드(Side)를 대상 뷰의 아래쪽 사이드(Side)에 맞춤.
layout_constraintBaseline_toBaselineOf 뷰의 텍스트 Baseline을 대상 뷰의 텍스트 Baseline에 맞춤.
layout_constraintStart_toEndOf 뷰의 시작 사이드(Side)를 대상 뷰의 끝 사이드(Side)에 맞춤.
layout_constraintStart_toStartOf 뷰의 시작 사이드(Side)를 대상 뷰의 시작 사이드(Side)에 맞춤.
layout_constraintEnd_toStartOf 뷰의 끝 사이드(Side)를 대상 뷰의 시작 사이드(Side)에 맞춤.
layout_constraintEnd_toEndOf 뷰의 끝 사이드(Side)를 대상 뷰의 끝 사이드(Side)에 맞춤.

위와 같은 속성으로 위치를 정해준다

Left, Right도 가능하지만 Start, End를 사용하는 것을 권장한다.

 

Constraint는 width, height를 0dp (match constraint), wrap_content로 둘 수 있다.

match_parent도 가능하고, 설정하면 관련 제약은 설정하지 않아도 된다.

다만 0dp로 제약을 걸어주는 것을 추천한다. 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.google.android.material.imageview.ShapeableImageView
        android:id="@+id/iv_suzy_image"
        android:layout_width="84dp"
        android:layout_height="84dp"
        android:src="@drawable/수지"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:shapeAppearanceOverlay="@style/CircularImageView" />

    <com.google.android.material.imageview.ShapeableImageView
        android:id="@+id/iv_siro_image"
        android:layout_width="84dp"
        android:layout_height="84dp"
        android:src="@drawable/흰둥이"
        app:layout_constraintEnd_toStartOf="@id/iv_jjangu_image"
        app:layout_constraintStart_toEndOf="@id/iv_suzy_image"
        app:layout_constraintTop_toTopOf="parent"
        app:shapeAppearanceOverlay="@style/CircularImageView" />

    <com.google.android.material.imageview.ShapeableImageView
        android:id="@+id/iv_jjangu_image"
        android:layout_width="84dp"
        android:layout_height="84dp"
        android:src="@drawable/짱구"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:shapeAppearanceOverlay="@style/CircularImageView" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

start와 end에 이미지를 놓고

각각의 끝에 흰둥이를 넣었다.

한쪽에만 제약을 걸었다면 한쪽에만 치우치게 된다.

양 끝에 제약을 주면 다음과 같이 가운데에 놓인다

 

 

4. 제약 조건 Chain 활용하기

지금은 흰둥이 이미지뷰에 만 제약을 넣어준 상태이다.

app:layout_constraintEnd_toStartOf="@id/iv_jjangu_image"
app:layout_constraintStart_toEndOf="@id/iv_suzy_image"

수지의 End 제약을 흰둥이에게

짱구의 Start 제약을 흰둥이에게 각각 걸어주면 체인이 활성화 된다.

 

다음과 같은 형태로 뷰가 배치된다.

양 끝의 마진과 뷰 사이간의 거리가 일정하다.

이는 코드로 다음과 같이 표현할 수 있다.

app:layout_constraintHorizontal_chainStyle="spread"

spread는 지금과 같은 형태를 나타낸다

chain의 기본값이기도 하다. 다른 속성을 알아보자

 

packed 속성

체인이 활성화된 뷰들끼리 딱 달라붙는다.

 

 

spread-inside

양 끝 뷰들은 parent 혹은 view에 붙어있고 간격이 일정하게 가운데 이미지가 표시된다

chain을 하지 않는 것도 같다.

 

 

4. 주요 속성 정리

Baseline

text에 한해서 baseline을 지정할 수 있다.

다음과 같이 bottomToBottom을 하게 되면 서로 라인이 맞지 않는다.
이는 toptotop 속성을 지정하여 가운데이 맞춰도 똑같다.

이럴때 텍스트끼리 라인을 맞추는 것이 baseline이다.

app:layout_constraintBaseline_toBaselineOf="@id/tv_constraint_title"

이렇게 하면 따로 마진을 주지 않아도 텍스트의 라인이 맞는다.

 

Margin

제약조건 사이의 여백을 주는 속성이다.

여백에 들어가는 값은 오직 0 또는 양수값만 적용할 수 있다.

  • android:layout_marginStart
  • android:layout_marginEnd
  • android:layout_marginTop
  • android:layout_marginBottom
  • android:layout_marginVertical
  • android:layout_marginHorizontal

마진 속성도 Left, Right가 있지만, Start, End를 권장한다.

Vertical과 Horizontal은 각각 수직, 수평으로 양쪽 모두 여백을 준다.

만약, 제약을 주지 않은 곳에 마진을 준다면 해당 속성은 무시된다.

제약을 준 곳만 여백을 줄 수 있다.

 

Bias

뷰를 일정 비율에 따라 배치하고 싶다면 Bias를 이용하면 된다.
우선 원하는 비율에 따라 수평, 수직의 제약을 모두 걸어준다.

 

<com.google.android.material.imageview.ShapeableImageView
    android:id="@+id/iv_siro_image"
    android:layout_width="184dp"
    android:layout_height="184dp"
    android:src="@drawable/흰둥이"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:shapeAppearanceOverlay="@style/CircularImageView" />

흰둥이 이미지에 수직 제약을 모두 주었다.

수평도 주었지만 이는 bias와 관계가 없다.

 

app:layout_constraintVertical_bias="0.3"

 

해당 속성을 주면 위쪽으로 0.3의 비율을 갖는다.

수평은 constraintHorizontal_bias