제약 조건 및 수정자 순서

Compose에서는 여러 수정자를 함께 체이닝하여 컴포저블의 모양과 느낌을 변경할 수 있습니다. 이러한 수정자 체인은 너비와 높이 경계를 정의하는 컴포저블에 전달되는 제약 조건 에 영향을 줄 수 있습니다.

이 페이지에서는 체이닝된 수정자가 제약 조건에 미치는 영향과 결과적으로 컴포저블의 측정 및 배치에 미치는 영향을 설명합니다.

UI 트리의 수정자

수정자가 서로에게 미치는 영향을 이해하려면 컴포지션 단계에서 생성되는 UI 트리에 수정자가 표시되는 방식을 시각화하는 것이 좋습니다. 자세한 내용은 컴포지션 섹션을 참고하세요.

UI 트리에서 수정자를 레이아웃 노드의 래퍼 노드로 시각화할 수 있습니다.

컴포저블 및 수정자의 코드와 UI 트리로 시각적으로 표현된 모습
그림 1. UI 트리의 레이아웃 노드를 래핑하는 수정자

컴포저블에 두 개 이상의 수정자를 추가하면 수정자 체인이 생성됩니다. 여러 수정자를 체이닝하면 각 수정자 노드가 체인의 나머지 부분과 레이아웃 노드를 래핑 합니다. 예를 들어 clipsize 수정자를 체이닝하면 clip 수정자 노드가 size 수정자 노드를 래핑하고, Image 레이아웃 노드를 래핑합니다.

레이아웃 단계에서 트리를 탐색하는 알고리즘은 동일하게 유지되지만 각 수정자 노드도 방문합니다. 이렇게 하면 수정자가 래핑하는 수정자 또는 레이아웃 노드의 크기 요구사항과 배치를 변경할 수 있습니다.

그림 2와 같이 ImageText 컴포저블 자체의 구현은 단일 레이아웃 노드를 래핑하는 수정자 체인으로 구성됩니다.

RowColumn의 구현은 하위 요소를 배치하는 방법을 설명하는 레이아웃 노드입니다.

이전의 트리 구조이지만 이제 각 노드는 단순한 레이아웃이며 많은 수정자가 노드를 감싸고 있습니다.
그림 2. 그림 1과 동일한 트리 구조이지만 UI 트리의 컴포저블이 수정자 체인으로 시각화됩니다.

요약

  • 수정자는 단일 수정자 또는 레이아웃 노드를 래핑합니다.
  • 레이아웃 노드는 여러 하위 노드를 배치할 수 있습니다.

다음 섹션에서는 이 정신 모델을 사용하여 수정자 체이닝과 이것이 컴포저블 크기에 미치는 영향을 추론하는 방법을 설명합니다.

레이아웃 단계의 제약 조건

레이아웃 단계는 3단계 알고리즘에 따라 각 레이아웃 노드의 너비, 높이, x, y 좌표를 찾습니다.

  1. 하위 요소 측정: 노드가 하위 요소를 측정합니다(있는 경우).
  2. 자체 크기 결정: 이러한 측정을 기반으로 노드가 자체 크기를 결정합니다.
  3. 하위 요소 배치: 각 하위 노드는 노드의 자체 위치를 기준으로 배치됩니다.

Constraints는 알고리즘의 처음 두 단계에서 노드의 적절한 크기를 찾는 데 도움이 됩니다. 제약 조건은 노드의 너비와 높이의 최소 및 최대 경계를 정의합니다. 노드가 자체 크기를 결정할 때 측정된 크기는 이 크기 범위 내에 있어야 합니다.

제약 조건 유형

제약 조건은 다음 중 하나일 수 있습니다.

  • 경계: 노드의 최대 및 최소 너비와 높이가 있습니다.
컨테이너 내에서 크기가 다른 제한된 제약 조건
그림 3. 경계 제약 조건
  • 무제한: 노드의 크기가 제한되지 않습니다. 최대 너비 및 높이 경계는 무한대로 설정됩니다.
너비와 높이가 무한대로 설정된 무한 제약 조건입니다. 제약 조건이 컨테이너를 벗어납니다.
그림 4. 무제한 제약 조건
  • 정확: 노드가 정확한 크기 요구사항을 따르도록 요청됩니다. 최소 및 최대 경계는 동일한 값으로 설정됩니다.
컨테이너 내의 정확한 크기 요구사항을 준수하는 정확한 제약 조건입니다.
그림 5. 정확한 제약 조건
  • 조합: 노드가 이전 제약 조건 유형의 조합을 따릅니다. 예를 들어 제약 조건은 너비를 제한하면서 무제한 최대 높이를 허용하거나 정확한 너비를 설정하지만 경계 높이를 제공할 수 있습니다.
경계가 있는 제약 조건과 경계가 없는 제약 조건, 정확한 너비와 높이의 조합을 보여주는 두 개의 컨테이너
그림 6. 경계 및 무제한 제약 조건과 정확한 너비 및 높이의 조합

다음 섹션에서는 이러한 제약 조건이 상위 요소에서 하위 요소로 전달되는 방법을 설명합니다.

제약 조건이 상위 요소에서 하위 요소로 전달되는 방법

레이아웃 단계의 제약 조건 에 설명된 알고리즘의 첫 번째 단계에서 제약 조건은 UI 트리의 상위 요소에서 하위 요소 로 전달됩니다.

상위 노드가 하위 노드를 측정할 때 각 하위 노드에 이러한 제약 조건을 제공하여 하위 노드가 얼마나 크거나 작을 수 있는지 알립니다. 그런 다음 자체 크기를 결정할 때 자체 상위 요소에서 전달된 제약 조건도 준수합니다.

상위 수준에서 알고리즘은 다음과 같이 작동합니다.

  1. 실제로 차지하려는 크기를 결정하기 위해 UI 트리의 루트 노드는 하위 요소를 측정하고 동일한 제약 조건을 첫 번째 하위 요소에 전달합니다.
  2. 하위 요소가 측정에 영향을 미치지 않는 수정자인 경우 제약 조건을 다음 수정자에 전달합니다. 측정에 영향을 미치는 수정자에 도달하지 않는 한 제약 조건은 수정자 체인에 그대로 전달됩니다. 그러면 제약 조건의 크기가 적절하게 조정됩니다.
  3. 하위 요소가 없는 노드 (리프 노드라고 함)에 도달하면 전달된 제약 조건을 기반으로 크기를 결정하고 이 해결된 크기를 상위 요소에 반환합니다.
  4. 상위 요소는 이 하위 요소의 측정을 기반으로 제약 조건을 조정하고 이러한 조정된 제약 조건으로 다음 하위 요소를 호출합니다.
  5. 상위 요소의 모든 하위 요소가 측정되면 상위 노드는 자체 크기를 결정하고 이를 자체 상위 요소에 전달합니다.
  6. 이렇게 하면 전체 트리가 깊이 우선으로 탐색됩니다. 결국 모든 노드가 크기를 결정하고 측정 단계가 완료됩니다.

자세한 예는 제약 조건 및 수정자 순서 동영상을 참고하세요.

제약 조건에 영향을 미치는 수정자

이전 섹션에서 일부 수정자가 제약 조건 크기에 영향을 줄 수 있다는 것을 배웠습니다. 다음 섹션에서는 제약 조건에 영향을 미치는 특정 수정자를 설명합니다.

size 수정자

size 수정자는 콘텐츠의 선호 크기를 선언합니다.

예를 들어 다음 UI 트리는 300dp x 200dp 컨테이너에서 렌더링되어야 합니다. 제약 조건은 경계가 지정되어 100dp300dp 사이의 너비와 100dp200dp 사이의 높이를 허용합니다.

레이아웃 노드를 래핑하는 size 수정자가 있는 UI 트리의 일부와 컨테이너의 size 수정자로 설정된 바운드 제약 조건의 표현
그림 7. UI 트리의 경계 제약 조건과 컨테이너의 표현

size 수정자는 수신하는 제약 조건을 전달된 값과 일치하도록 조정합니다. 이 예에서 값은 150dp입니다.

그림 7과 동일하지만 크기 수정자가 수신하는 제약 조건을 전달된 값과 일치하도록 조정합니다.
그림 8. size 수정자가 제약 조건을 150dp로 조정합니다.

너비와 높이가 가장 작은 제약 조건 경계보다 작거나 가장 큰 제약 조건 경계보다 큰 경우 수정자는 전달된 제약 조건을 최대한 일치시키면서 전달된 제약 조건을 준수합니다.

두 UI 트리와 컨테이너의 해당 표현 첫 번째에서는 size 수정자가 수신되는 제약 조건을 허용합니다. 두 번째에서는 size 수정자가 너무 큰 제약 조건에 최대한 가깝게 적응하여 컨테이너를 채우는 제약 조건이 생성됩니다.
그림 9. size 수정자가 전달된 제약 조건을 최대한 준수합니다.

여러 size 수정자를 체이닝하는 것은 작동하지 않습니다. 첫 번째 size 수정자는 최소 및 최대 제약 조건을 모두 고정 값으로 설정합니다. 두 번째 크기 수정자가 더 작거나 큰 크기를 요청하더라도 전달된 정확한 경계를 준수해야 하므로 이러한 값을 재정의하지 않습니다.

UI 트리의 두 크기 수정자 체인과 컨테이너의 표현으로, 전달된 첫 번째 값의 결과이며 두 번째 값의 결과가 아닙니다.
그림 10. 두 개의 size 수정자 체인으로, 전달된 두 번째 값(50dp)이 첫 번째 값(100dp)을 재정의하지 않습니다.

requiredSize 수정자

노드가 수신 제약 조건을 재정의해야 하는 경우 size 대신 requiredSize 수정자를 사용하세요. requiredSize 수정자는 수신 제약 조건을 대체하고 지정한 크기를 정확한 경계로 전달합니다.

크기가 트리 위로 다시 전달되면 하위 노드가 사용 가능한 공간의 중앙에 배치됩니다.

UI 트리에서 체이닝된 size 및 requiredSize 수정자와 컨테이너의 해당 표현 requiredSize 수정자 제약 조건은 size 수정자 제약 조건을 재정의합니다.
그림 11. requiredSize 수정자가 size 수정자의 수신 제약 조건을 재정의합니다.

widthheight 수정자

size 수정자는 제약 조건의 너비와 높이를 모두 조정합니다. width 수정자를 사용하면 고정 너비를 설정할 수 있지만 높이는 결정되지 않은 상태로 둘 수 있습니다. 마찬가지로 height 수정자를 사용하면 고정 높이를 설정할 수 있지만 너비는 결정되지 않은 상태로 둘 수 있습니다.

너비 수정자와 컨테이너 표현이 있는 UI 트리 하나와 높이 수정자와 표현이 있는 UI 트리 하나
그림 12. width 수정자와 height 수정자가 각각 고정 너비와 높이를 설정합니다.

sizeIn 수정자

sizeIn 수정자를 사용하면 너비와 높이에 대한 정확한 최소 및 최대 제약 조건을 설정할 수 있습니다. 제약 조건을 세밀하게 제어해야 하는 경우 sizeIn 수정자를 사용하세요.

최소 및 최대 너비와 높이가 설정된 sizeIn 수정자가 있는 UI 트리와 컨테이너 내 표현
그림 13. minWidth, maxWidth, minHeight, maxHeight가 설정된 sizeIn 수정자

이 섹션에서는 체이닝된 수정자가 있는 여러 코드 스니펫의 출력을 보여주고 설명합니다.

Image(
    painterResource(R.drawable.hero),
    contentDescription = null,
    Modifier
        .fillMaxSize()
        .size(50.dp)
)

이 스니펫은 다음 출력을 생성합니다.

상위 컨테이너를 채우는 파란색 정사각형
그림 14. Image는 수정자 체인의 결과로 최대 크기를 채웁니다.
  • fillMaxSize 수정자는 최소 너비와 높이를 모두 최대값으로 설정하도록 제약 조건을 변경합니다. 너비는 300dp, 높이는 200dp 입니다.
  • size 수정자가 50dp 크기를 사용하려고 하지만 수신 최소 제약 조건을 준수해야 합니다. 따라서 size 수정자는 300 x 200의 정확한 제약 조건 경계를 출력하여 size 수정자에 제공된 값을 효과적으로 무시합니다.
  • Image는 이러한 경계를 따르고 300 x 200 크기를 보고하며 이는 트리 전체에 전달됩니다.

Image(
    painterResource(R.drawable.hero),
    contentDescription = null,
    Modifier
        .fillMaxSize()
        .wrapContentSize()
        .size(50.dp)
)

이 스니펫은 다음 출력을 생성합니다.

상위 컨테이너 내에 중앙에 배치된 작은 파란색 정사각형
그림 15. Image는 중앙에 배치되고 크기가 50dp로 조정됩니다.
  • fillMaxSize 수정자는 최소 너비와 높이를 모두 최대값으로 설정하도록 제약 조건을 조정합니다. 너비는 300dp, 높이는 200dp입니다.
  • wrapContentSize 수정자는 최소 제약 조건을 재설정합니다. 따라서 fillMaxSize는 고정 제약 조건을 생성했지만 wrapContentSize경계 제약 조건으로 다시 재설정 합니다. 이제 다음 노드가 전체 공간을 다시 차지하거나 전체 공간보다 작을 수 있습니다.
  • size 수정자는 제약 조건을 최소 및 최대 경계 50으로 설정합니다.
  • Image50 x 50 크기로 확인되고 size 수정자는 이를 전달합니다.
  • wrapContentSize 수정자에는 특별한 속성이 있습니다. 하위 요소를 가져와서 전달된 사용 가능한 최소 경계의 중앙에 배치 합니다. 따라서 상위 요소에 전달하는 크기는 전달된 최소 경계와 같습니다.

수정자 세 개만 결합하여 컴포저블의 크기를 정의하고 상위 요소의 중앙에 배치할 수 있습니다.

Image(
    painterResource(R.drawable.hero),
    contentDescription = null,
    Modifier
        .clip(CircleShape)
        .padding(10.dp)
        .size(100.dp)
)

이 스니펫은 다음 출력을 생성합니다.

수정자 순서로 인해 잘못 클리핑된 원형 모양
그림 16. 수정자 순서로 인해 잘못 잘린 도형
  • clip 수정자는 제약 조건을 변경하지 않습니다.
  • padding 수정자는 최대 제약 조건을 낮춥니다.
  • size 수정자는 모든 제약 조건을 100dp로 설정합니다.
  • Image는 이러한 제약 조건을 준수하고 100dp x 100dp 크기를 보고합니다.
  • padding 수정자는 Image에서 보고한 크기에 모든 면에서 10dp를 추가하므로 패딩이 있는 레이아웃은 너비와 높이를 120dp로 보고합니다.
  • 이제 그리기 단계에서 clip 수정자는 120dp x 120dp 캔버스에서 작동합니다. 이 크기의 원형 마스크를 만듭니다.
  • 그런 다음 padding 수정자는 모든 면에서 콘텐츠를 10dp로 삽입하여 Image의 캔버스 크기를 100dp x 100dp로 낮춥니다.
  • Image는 더 작은 캔버스에 그려집니다. 이미지는 원래 120dp 원을 기반으로 잘리므로 출력은 원형이 아닌 결과입니다.