[Android] ConstraintLayout 알아보기

hxeyexn·2023년 10월 19일
0
post-thumbnail

Intro

ConstraintLayout을 사용하는 목적에 대해서는 이해했지만, 쇼핑몰 프로젝트를 진행하면서 ConstraintLayout의 장점을 잘 활용하지 못하고 있는 느낌을 받았다.

이에 따라 ConstraintLayout의 개념부터 다시 제대로 공부해보려고 한다!


ConstraintLayout이란?

상대 위치에 따라 유연한 방식으로 위젯의 위치와 크기를 지정할 수 있는 layout

  • ConstraintLayout을 사용하면 중첩 뷰 그룹이 없는 flat view layout 구조로 크고 복잡한 레이아웃을 만들 수 있다
  • 레이아웃을 평탄화할 수 있다는 점이 핵심이다!


중첩된 뷰 그룹의 문제점

  • 복잡한 레이아웃을 ConstraintLayout이 아닌 LinearLayout로 작성하게 되면 뷰 그룹 중첩이 엄청 많이 발생한다
  • 이렇게 되면 뷰를 그리는데 시간이 엄청 오래 걸린다
    ➡️ Why? 계산된 부모에 따라 뷰의 높이가 변한다면, 처음부터 모든 것을 다시 계산해야하기 때문이다. 부모부터 계산을 시작해서 하위로 내려간다면 끝날 때까지 이런 계산이 계속된다

이렇게 우리가 레이아웃 속도에 관심을 가져야 하는 이유는 부드러운 UI를 위해서는 한정된 시간에 보여줘야 하기 때문이다


RelativeLayout vs ConstraintLayout

얼핏 보기엔 RelativeLayout과 비슷하다
두가지 뷰 그룹 모두 모든 뷰를 형제 뷰와 부모 레이아웃 관계에 따라 배치할 수 있다는 특성을 가지고 있기 때문이다

하지만 ConstraintLayout이 좀 더 유연하고 Android Studio의 Layout Editor와 사용하기 더 쉽다고 한다


app:layout_constraintStart_toStartOf="parent" 는 무슨 뜻일까?

ConstraintLayout을 사용할 때 위 속성이 가장 중요하다고 생각한다

<androidx.recyclerview.widget.RecyclerView
	android:id="@+id/rv_communityfeed_feed"
    ...
    app:layout_constraintStart_toStartOf="parent"
    ... />

위 코드는 해당 RecyclerView의 시작점에 제약을 주는데 부모의 시작점에 제약을 걸겠다는 의미이다
이를 제약 조건이라고 한다


제약(constraints) 조건

ConstraintLayout은 이름 그대로 뷰를 화면에 출력할 때 제약 조건을 지정해줘야 한다

제약조건 규칙

  1. 모든 보기에는 가로와 세로 하나씩 두 개 이상의 제약조건이 있어야 한다
    ➡️ 즉, Start와 End 중 하나, Top과 Bottom 중 하나씩은 제약조건이 필요

<androidx.recyclerview.widget.RecyclerView
	android:id="@+id/rv_communityfeed_feed"
    ...
	app:layout_constraintStart_toStartOf="parent"   // 가로 제약 조건
    app:layout_constraintTop_toTopOf="parent"   // 세로 제약 조건
    ... />
  1. 같은 평면을 공유하는 제약조건 핸들과 앵커 포인트 사이에만 제약조건을 만들 수 있다
    ➡️ 세로 평면은 다른 세로 평면으로만 제한

    ➡️ 가로 평면은 다른 가로 평면으로만 제한

  2. 각 제약조건 핸들은 하나의 제약조건에만 사용할 수 있지만 동일한 앵커 포인트에 여러 개의 제약조건(다른 view에서)을 만들 수 있다



학습 내용 프로젝트에 적용하기

백문불여일견이라고.. 백날 글로만 보면 모른다 직접 해보자
진행 중인 프로젝트의 피드 리스트 아이템을 만드는 데 적용해봤다

중첩 뷰 그룹없이 ConstraintLayout만으로 깔끔하게 UI가 짜졌다!
아직 조금 헷갈리는 부분이 있지만 이전보다 훨씬 코드가 깔끔해진 것 같다 😁

코드

<?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"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="21dp">

    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/civ_itemfeed_profile"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:src="@drawable/profile_default_image"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv_itemfeed_nickname"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginBottom="10dp"
        android:text="비건 라이프"
        android:textSize="14sp"
        android:textStyle="bold"
        app:layout_constraintStart_toEndOf="@id/civ_itemfeed_profile"
        app:layout_constraintTop_toTopOf="@id/civ_itemfeed_profile" />

    <TextView
        android:id="@+id/tv_itemfeed_date"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:gravity="center_vertical"
        android:text="10월 26일"
        android:textColor="#545454"
        android:textSize="10sp"
        app:layout_constraintBottom_toBottomOf="@id/civ_itemfeed_profile"
        app:layout_constraintStart_toEndOf="@id/civ_itemfeed_profile" />

    <TextView
        android:id="@+id/tv_itemfeed_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="성동구 비건 베이커리 추천"
        android:textSize="12sp"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/civ_itemfeed_profile" />

    <TextView
        android:id="@+id/tv_itemfeed_description"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="6dp"
        android:layout_marginEnd="16dp"
        android:ellipsize="end"
        android:maxLines="2"
        android:text="고즈넉하고 아기자기한 가게와 친절한 사장님이 계시는 성동구 비건 베이커리! 무려 비건 앙버터를 먹을 수 있는 곳 ㅠㅠ ♥ 시나몬롤도 달달 고소하고 맛있었어요 모두 비건이에요 :)"
        android:textSize="12sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@id/cv_itemfeed_image"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/tv_itemfeed_title" />

    <androidx.cardview.widget.CardView
        android:id="@+id/cv_itemfeed_image"
        android:layout_width="85dp"
        android:layout_height="85dp"
        app:cardCornerRadius="4dp"
        app:cardElevation="0dp"
        app:layout_constraintBottom_toBottomOf="@id/tv_itemfeed_description"
        app:layout_constraintEnd_toEndOf="parent">

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:contentDescription="피드 이미지"
            android:src="@drawable/default_image" />

    </androidx.cardview.widget.CardView>

</androidx.constraintlayout.widget.ConstraintLayout>


📚 참고자료

Android Docs : ConstraintLayout으로 반응형 UI 빌드
안드로이드 ConstraintLayout 개념과 사용법 정복하기
Android ConstraintLayout 쉽게 알아가자
ConstraintLayout Docs
Do it! 깡샘의 안드로이드 앱 프로그래밍 with 코틀린

profile
Android Developer

0개의 댓글