|

Android ConstraintLayout 완전 정리 (5) – ConstraintLayout match_constraint 완전 정리: 0dp가 남은 공간을 채우는 원리

Android ConstraintLayout 완전 정리 (5) – ConstraintLayout match_constraint 완전 정리: 0dp가 남은 공간을 채우는 원리
ConstraintLayout은 XML 코드와 실제 배치 결과를 같이 볼 때 이해가 빨라집니다.

ConstraintLayout match_constraint는 0dp를 실전에서 제대로 쓰기 위해 꼭 이해해야 하는 개념입니다. 4편에서 0dp가 크기 0이 아니라 제약 기준 크기 계산이라는 점을 봤다면, 이번 편은 그 계산이 언제 성공하고 언제 실패하는지 더 구체적으로 봅니다.

핵심은 단순합니다. match_constraint는 양쪽 제약 사이의 사용 가능한 공간을 채우고, 필요하면 min/max로 크기를 제한합니다.

ConstraintLayout match_constraint 성공 실패 제한 비교 이미지
match_constraint는 제약이 충분할 때 남은 공간을 계산하고, 필요하면 min/max로 제한합니다.

ConstraintLayout match_constraint는 0dp의 실제 의미다

ConstraintLayout에서 width나 height를 0dp로 쓰면 대부분 MATCH_CONSTRAINT로 동작합니다. 즉, View가 스스로 내용 크기를 정하는 wrap_content도 아니고, 개발자가 고정값을 주는 fixed dp도 아닙니다. 제약 관계를 보고 사용할 수 있는 크기를 계산합니다.

  • wrap_content: 내용이 크기 기준
  • fixed dp: 지정한 값이 크기 기준
  • 0dp / match_constraint: 제약 사이 사용 가능한 공간이 크기 기준

그래서 match_constraint를 볼 때는 XML 한 줄만 보면 안 됩니다. 반드시 같은 방향의 제약을 함께 봐야 합니다. width=0dp라면 start와 end를 보고, height=0dp라면 top과 bottom을 봅니다.


parent 양끝 사이를 채우는 가장 작은 예

가장 단순한 성공 예시는 View의 width를 0dp로 두고 start와 end를 모두 parent에 연결하는 것입니다. 이때 View는 parent 안에서 사용할 수 있는 가로 공간을 채웁니다.

<TextView
    android:id="@+id/bannerText"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:text="Full width banner"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
ConstraintLayout match_constraint parent 양끝 사이 채우기 예시
0dp와 parent 양쪽 제약을 함께 쓰면 parent 안의 사용 가능한 폭을 채울 수 있습니다.

이 구조는 match_parent처럼 보일 수 있습니다. 하지만 ConstraintLayout 안에서는 parent 양쪽 제약과 0dp 조합으로 읽는 편이 더 자연스럽습니다. 나중에 margin, bias, min/max, ratio와도 이어지기 때문입니다.


아이콘 옆 TextView는 match_constraint가 잘 맞는다

실무에서 가장 자주 보는 패턴은 아이콘 옆의 긴 텍스트입니다. 아이콘은 48dp처럼 고정 크기이고, 텍스트는 아이콘 오른쪽부터 parent 끝까지 남은 폭을 사용해야 합니다.

<ImageView
    android:id="@+id/iconImage"
    android:layout_width="48dp"
    android:layout_height="48dp"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<TextView
    android:id="@+id/titleText"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginStart="16dp"
    android:text="Long title can use remaining space"
    app:layout_constraintStart_toEndOf="@id/iconImage"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="@id/iconImage" />
ConstraintLayout match_constraint 아이콘 옆 TextView 남은 공간 예시
아이콘 옆 긴 텍스트는 0dp와 end 제약으로 parent 밖으로 밀리지 않게 만들 수 있습니다.

titleText는 iconImage의 end와 parent의 end 사이를 사용합니다. marginStart 16dp가 있으므로 실제로는 아이콘과의 간격을 제외한 남은 공간을 씁니다. 긴 제목이 parent 밖으로 밀리는 문제를 줄이는 데 좋은 구조입니다.

  • 왼쪽 View: 고정 크기
  • 오른쪽 TextView: width=0dp
  • 오른쪽 TextView의 start: 왼쪽 View의 end
  • 오른쪽 TextView의 end: parent end

버튼 사이 중간 영역도 같은 원리다

양쪽에 고정 폭 버튼이 있고 가운데 입력 영역만 늘어나야 하는 화면도 같은 원리로 만들 수 있습니다. 가운데 View를 0dp로 두고, start와 end를 양쪽 버튼에 연결합니다.

<Button
    android:id="@+id/cancelButton"
    android:layout_width="wrap_content"
    android:layout_height="48dp"
    android:text="Cancel"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<EditText
    android:id="@+id/inputText"
    android:layout_width="0dp"
    android:layout_height="48dp"
    android:layout_marginStart="12dp"
    android:layout_marginEnd="12dp"
    app:layout_constraintStart_toEndOf="@id/cancelButton"
    app:layout_constraintEnd_toStartOf="@id/okButton"
    app:layout_constraintTop_toTopOf="@id/cancelButton" />

<Button
    android:id="@+id/okButton"
    android:layout_width="wrap_content"
    android:layout_height="48dp"
    android:text="OK"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
ConstraintLayout match_constraint 버튼 사이 공간 채우기 예시
고정 폭 View 사이에 있는 0dp View는 양쪽 제약 사이의 남은 공간을 사용할 수 있습니다.

이 예제에서 inputText는 parent 전체가 아니라 cancelButton과 okButton 사이의 공간만 사용합니다. match_constraint는 항상 화면 전체를 채우는 속성이 아니라, 연결된 제약 사이의 공간을 쓰는 속성입니다.


실패 조건은 제약 누락에서 시작한다

match_constraint가 이상하게 보일 때 가장 먼저 볼 것은 제약 누락입니다. width=0dp라면 가로 방향 끝점이 필요합니다. start만 있고 end가 없으면 사용할 수 있는 가로 공간의 끝을 알기 어렵습니다.

<!-- 실패하기 쉬운 예: width=0dp인데 end 제약이 없다 -->
<TextView
    android:id="@+id/titleText"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:text="Title"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
ConstraintLayout match_constraint 가로 세로 제약 누락 실수 이미지
width=0dp는 가로 제약, height=0dp는 세로 제약을 먼저 확인해야 합니다.

세로도 같습니다. height=0dp를 쓰려면 top과 bottom을 함께 확인해야 합니다. 가로 문제를 세로 속성에서 찾거나, 세로 문제를 가로 속성에서 찾으면 디버깅 시간이 길어집니다.

  • width=0dp: start와 end를 먼저 확인
  • height=0dp: top과 bottom을 먼저 확인
  • 기준 View가 GONE이 될 수 있으면 goneMargin도 함께 확인
  • margin이 너무 커서 남은 공간이 없어지는지도 확인

minWidth와 maxWidth로 남은 공간을 제한한다

match_constraint는 사용 가능한 공간을 채우지만, 실무에서는 너무 작아지거나 너무 커지는 것을 막아야 할 때가 있습니다. 이때 minWidth와 maxWidth 계열 속성을 함께 쓸 수 있습니다.

<TextView
    android:id="@+id/titleText"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:minWidth="120dp"
    app:layout_constraintWidth_max="240dp"
    android:text="Title"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
ConstraintLayout match_constraint minWidth maxWidth 제한 예시
minWidth와 maxWidth는 match_constraint로 계산된 크기에 최소/최대 경계를 둡니다.

minWidth는 최소 폭을 보장하고, maxWidth는 최대 폭을 제한합니다. 다만 이것만으로 모든 긴 텍스트 문제가 해결되지는 않습니다. TextView라면 줄바꿈, maxLines, ellipsize 같은 텍스트 표시 정책도 함께 정해야 합니다.

  • 너무 작아지면 버튼이나 텍스트가 읽기 어려운 경우: minWidth
  • 태블릿에서 View가 너무 넓어지는 경우: maxWidth
  • 긴 텍스트 처리: maxLines, ellipsize, 줄바꿈 정책도 함께 검토

percent와 ratio는 여기서 이어진다

공식 레퍼런스는 match_constraint에 percent와 dimensionRatio 같은 추가 조건도 설명합니다. 다만 이 편에서 모두 깊게 다루면 핵심이 흐려집니다. percent 크기는 9편, dimensionRatio는 8편에서 이미지 중심으로 따로 정리합니다.

이번 편에서 기억할 것은 하나입니다. percent와 ratio도 결국 제약 기반 크기 계산 위에 조건을 더하는 방식입니다. 그래서 0dp와 양쪽 제약을 먼저 이해해두면 후속 속성이 훨씬 쉬워집니다.


실무 판단 기준

  • 한 방향으로만 제약이 있으면 match_constraint부터 의심한다
  • 양쪽 제약이 있다면 남은 공간 계산이 가능한지 본다
  • 고정 View 옆 긴 텍스트는 0dp가 유리한 경우가 많다
  • 너무 작거나 커지는 문제는 min/max로 제한한다
  • 텍스트 overflow는 크기 계산과 텍스트 표시 정책을 함께 본다

match_constraint를 잘 쓰면 ConstraintLayout XML이 오히려 읽기 쉬워집니다. “이 View는 남은 공간을 쓰는 역할”이라고 명확해지기 때문입니다. 반대로 아무 View에나 0dp를 넣으면 제약 누락과 크기 제한 문제를 동시에 만들 수 있습니다.


정리

ConstraintLayout match_constraint는 0dp의 실전 의미입니다. 사용 가능한 공간을 채우되, 그 공간은 연결된 제약과 margin에 의해 정해집니다. 성공 조건은 양쪽 제약이고, 대표 실패 조건은 제약 누락입니다.

  • 0dp는 match_constraint로 읽는다
  • width=0dp는 가로 양쪽 제약을 확인한다
  • height=0dp는 세로 양쪽 제약을 확인한다
  • min/max로 계산된 크기를 제한할 수 있다
  • percent와 ratio는 후속 편에서 더 깊게 다룬다

다음 편에서는 bias를 다룹니다. 양쪽 제약이 있는 View를 가운데가 아니라 왼쪽이나 오른쪽, 위쪽이나 아래쪽으로 어떻게 밀 수 있는지 정리하겠습니다.

아래에는 이 편보다 앞에서 다룬 글만 모았습니다. 아직 뒤 편은 발행 전이므로 링크하지 않습니다.

공식 기준은 Android Developers ConstraintLayout 가이드AndroidX ConstraintLayout 레퍼런스를 확인했습니다.

함께보면 좋은 글