[번역] Views with Intrinsic Content Size

작성일 :

개요


해당 문서는 학습 목적으로 Apple 공식 문서인 🔗 Auto Layout Guide을 번역한 글입니다. 다소 오역이 있을 수 있어 잘못된 내용이 있을 수 있습니다. 문제가 되거나 오류가 있다면 댓글 부탁드립니다.

내용


다음 예제는 고유한 콘텐츠 크기가 있는 뷰로 작업하는 방법을 보여줍니다. 일반적으로 고유 콘텐츠 크기는 레이아웃을 단순화하여 필요한 제약 조건의 수를 줄입니다. 그러나 고유한 콘텐츠 크기를 사용하려면 뷰의 content-hugging 및 compression-resistance(CHCR) 우선 순위를 설정해야 하는 경우가 많으며, 이로 인해 추가적인 복잡성이 추가될 수 있습니다.

이러한 레시피의 소스 코드를 보려면 Auto Layout Cookbook 프로젝트를 참조하십시오.

Simple Label and Text Field


이 예제는 간단한 레이블과 텍스트 필드 쌍을 배치하는 방법을 보여줍니다. 이 예에서 레이블의 너비는 텍스트 속성의 크기를 기반으로 하며 텍스트 필드는 나머지 공간에 맞게 확장 및 축소됩니다.

image01

이 예제는 뷰의 고유 콘텐츠 크기를 사용하기 때문에 레이아웃을 고유하게 지정하는 데 5개의 제약 조건만 필요합니다. 그러나 올바른 크기 조정 동작을 얻으려면 올바른 CHCR 우선 순위가 있는지 확인해야 합니다.

고유 콘텐츠 크기 및 CHCR 우선 순위에 대한 자세한 내용은 🔗 Intrinsic Content Size를 참조하세요.

Views and Constraints

Interface Builder에서 레이블과 텍스트 필드를 드래그합니다. 레이블의 텍스트와 텍스트 필드의 placeholder를 설정한 다음 그림과 같이 제약 조건을 설정합니다.

image02
  1. Name Label.Leading = Superview.LeadingMargin
  2. Name Text Field.Trailing = Superview.TrailingMargin
  3. Name Text Field.Leading = Name Label.Trailing + Standard
  4. Name Text Field.Top = Top Layout Guide.Bottom + 20.0
  5. Name label.Baseline = Name Text Field.Baseline

Attributes

사용 가능한 공간을 채우도록 텍스트 필드를 늘리려면 콘텐츠 허깅이 레이블보다 낮아야 합니다. 기본적으로 Interface Builder는 레이블의 콘텐츠 허깅을을 251로 설정하고 텍스트 필드를 250으로 설정해야 합니다. 크기 속성에서 이를 확인할 수 있습니다.

image03

Discussion

이 레이아웃은 수직 레이아웃을 정의하기 위해 2개의 제약 조건(4 및 5)과 수평 레이아웃을 정의하기 위해 3개의 제약 조건(1, 2 및 3)만 사용합니다. 🔗 Creating Nonambiguous, Satisfiable Layouts의 rule of thumb에 따르면 뷰당 2개의 수평 및 2개의 수직 제약 조건이 필요합니다. 그러나 레이블 및 텍스트 필드의 고유한 콘텐츠 크기는 높이와 레이블의 너비를 제공하므로 세 가지 제약 조건이 필요하지 않습니다.

또한 이 레이아웃은 텍스트 필드가 항상 레이블 텍스트보다 크다고 가정하고 텍스트 필드의 높이를 사용하여 상단 레이아웃 가이드로부터의 거리를 정의합니다. 레이블과 텍스트 필드는 모두 텍스트를 표시하는 데 사용되기 때문에 레시피는 텍스트의 기준선을 사용하여 정렬합니다.

수평으로 사용 가능한 크기를 채우기 위해 확장해야 하는 뷰를 정의해야 합니다. 뷰의 CHCR 우선 순위를 수정하여 이를 수행합니다. 이 예에서 Interface Builder는 이미 이름 레이블의 수평 및 수직 허깅 우선순위를 251로 설정해야 합니다. 이것은 텍스트 필드의 기본 250보다 크기 때문에 텍스트 필드가 확장되어 추가 공간을 채웁니다.

NOTE

레이아웃이 컨트롤에 비해 너무 작은 공간에 표시될 수 있는 경우 compression resistances값도 수정해야 합니다. compression resistances는 충분한 공간이 없을 때 잘라야 하는 뷰를 정의합니다.

이 예에서 compression resistances를 수정하는 것은 독자의 연습 문제로 남겨둡니다. 이름 레이블의 텍스트 또는 글꼴이 충분히 큰 경우 그러나 공간이 충분하지 않아 모호한 레이아웃이 생성됩니다. 그런 다음 시스템에서 중단할 제약 조건을 선택하고 텍스트 필드 또는 레이블이 잘립니다.

이상적으로는 필요에 따라 소형 클래스에 대한 대체 레이아웃을 사용하여 사용 가능한 공간에 비해 너무 크지 않은 레이아웃을 만들고자 합니다. 그러나 여러 언어 및 동적 유형을 지원하는 뷰를 디자인할 때 행이 얼마나 커질지 정확히 예측하기는 어렵습니다. 만일을 대비하여 compression resistances를 수정하는 것이 좋은 안전 장치입니다.

Dynamic Height Label and Text Field


🔗 Simple Label and Text Field 예제는 텍스트 필드가 항상 이름 레이블보다 크다고 가정하여 레이아웃 논리를 단순화했습니다. 그러나 항상 그런 것은 아닙니다. 레이블의 글꼴 크기를 충분히 늘리면 텍스트 필드 위로 확장됩니다.

이 레시피는 런타임 시 가장 높은 컨트롤을 기준으로 컨트롤의 세로 간격을 동적으로 설정합니다. 일반 시스템 글꼴을 사용하면 이 예제는 🔗 Simple Label and Text Field 예제와 동일하게 나타납니다(스크린샷 참조). 그러나 레이블의 글꼴 크기를 36.0포인트로 늘리면 레이아웃의 세로 간격이 대신 레이블의 상단부터 계산됩니다.

image04

이것은 다소 인위적인 예입니다. 결국 레이블의 글꼴 크기를 늘리면 일반적으로 텍스트 필드의 글꼴 크기도 커집니다. 그러나 iPhone의 접근성 설정을 통해 extra, extra, extra large fonts를 사용할 수 있는 경우 이 기술은 dynamic type과 fixed-sized controls(예: 이미지)을 혼합할 때 유용할 수 있습니다.

Views and Constraints

Simple Label and Text Field에서와 같이 뷰 계층 구조를 설정하지만 다소 복잡한 제약 조건 집합을 사용합니다.

image05
  1. Name Label.Leading = Superview.LeadingMargin
  2. Name Text Field.Trailing = Superview.TrailingMargin
  3. Name Text Field.Leading = Name Label.Trailing + Standard
  4. Name Label.Top >= Top Layout Guide.Bottom + 20.0
  5. Name Label.Top = Top Layout Guide.Bottom + 20.0 (Priority 249)
  6. Name Text Field.Top >= Top Layout Guide.Bottom + 20.0
  7. Name Text Field.Top = Top Layout Guide.Bottom + 20.0 (Priority 249)
  8. Name label.Baseline = Name Text Field.Baseline

Attributes

사용 가능한 공간을 채우도록 텍스트 필드를 늘리려면 콘텐츠 허깅이 레이블보다 낮아야 합니다. 기본적으로 Interface Builder는 레이블의 콘텐츠 허깅을 251로 설정하고 텍스트 필드를 250으로 설정해야 합니다. 크기 속성에서 이를 확인할 수 있습니다.

image06

Discussion

이 예제는 각 컨트롤에 대해 한 쌍의 제약 조건을 사용합니다. 크거나 같은 필수 제약 조건은 해당 컨트롤과 레이아웃 가이드 사이의 최소 거리를 정의하는 반면, 선택적 제약 조건은 레이아웃 가이드에서 정확히 20.0포인트로 컨트롤을 당기려고 시도합니다.

두 제약 조건 모두 더 큰 제약 조건에 대해 만족할 수 있으므로 시스템은 레이아웃 가이드에서 정확히 20.0포인트에 배치합니다. 그러나 더 짧은 control의 경우 최소 거리만 만족할 수 있습니다. 다른 제약 조건은 무시됩니다. 이렇게 하면 오토 레이아웃 시스템이 런타임 시 컨트롤의 높이가 변경됨에 따라 레이아웃을 동적으로 재계산할 수 있습니다.

NOTE

선택적 제약 조건의 우선 순위를 기본 콘텐츠 허깅 제약 조건(250)보다 낮은 값으로 설정해야 합니다. 그렇지 않으면 시스템이 콘텐츠 허깅 제약 조건을 깨고 위치를 변경하는 대신 뷰를 확장합니다.

이는 baseline alignments을 사용하는 레이아웃으로 작업할 때 특히 혼란스러울 수 있습니다. baseline alignments은 텍스트 뷰가 고유 콘텐츠 높이에 표시되는 경우에만 유효하기 때문입니다. 시스템에서 보기 중 하나의 크기를 조정하면 필요한 기준선 제약 조건이 있음에도 불구하고 텍스트가 제대로 정렬되지 않을 수 있습니다.

Fixed Height Columns


이 예제는 Simple Label and Text Field 예제를 레이블 및 텍스트 필드의 열로 확장합니다. 여기에서 모든 레이블의 trailing edge가 정렬됩니다. 텍스트 필드 leading 및 trailing edge가 정렬되고 가로 배치는 가장 긴 레이블을 기준으로 합니다. 그러나 Simple Label and Text Field 예제와 마찬가지로 이 예제는 텍스트 필드가 항상 레이블보다 높다고 가정하여 레이아웃 논리를 단순화합니다.

image07

Views and Constraints

레이블과 텍스트 필드를 배치한 다음 그림과 같이 제약 조건을 설정합니다.

image08
  1. First Name Label.Leading = Superview.LeadingMargin
  2. Middle Name Label.Leading = Superview.LeadingMargin
  3. Last Name Label.Leading = Superview.LeadingMargin
  4. First Name Text Field.Leading = First Name Label.Trailing + Standard
  5. Middle Name Text Field.Leading = Middle Name Label.Trailing + Standard
  6. Last Name Text Field.Leading = Last Name Label.Trailing + Standard
  7. First Name Text Field.Trailing = Superview.TrailingMargin
  8. Middle Name Text Field.Trailing = Superview.TrailingMargin
  9. Last Name Text Field.Trailing = Superview.TrailingMargin
  10. First Name Label.Baseline = First Name Text Field.Baseline
  11. Middle Name Label.Baseline = Middle Name Text Field.Baseline
  12. Last Name Label.Baseline = Last Name Text Field.Baseline
  13. First Name Text Field.Width = Middle Name Text Field.Width
  14. First Name Text Field.Width = Last Name Text Field.Width
  15. First Name Text Field.Top = Top Layout Guide.Bottom + 20.0
  16. Middle Name Text Field.Top = First Name Text Field.Bottom + Standard
  17. Last Name Text Field.Top = Middle Name Text Field.Bottom + Standard

Attributes

Attributes inspector에서 다음 속성을 설정합니다. 특히 모든 레이블의 텍스트를 오른쪽 정렬하십시오. 이렇게 하면 텍스트보다 긴 레이블을 사용할 수 있으며 여전히 텍스트 필드 옆의 가장자리를 정렬할 수 있습니다.

image09

각 쌍에 대해 레이블의 콘텐츠 허깅은 텍스트 필드보다 높아야 합니다. 다시 말하지만 Interface Builder는 이 작업을 자동으로 수행해야 합니다. 그러나 크기 속성에서 이러한 우선 순위를 확인할 수 있습니다.

image10

Discussion

이 레시피는 기본적으로 🔗 Simple Label and Text Field 레이아웃의 복사본 3개로 시작하여 하나가 다른 하나 위에 쌓입니다. 그러나 행이 제대로 정렬되도록 몇 가지 추가 작업을 수행해야 합니다.

먼저 각 레이블의 텍스트를 오른쪽 정렬하여 문제를 단순화합니다. 이제 모든 레이블을 동일한 너비로 만들 수 있으며 텍스트 길이에 관계없이 후행 가장자리를 쉽게 정렬할 수 있습니다. 또한 레이블의 컴프레셔 레지스턴스가 내용물을 허깅하는 것보다 크기 때문에 모든 레이블은 압착되는 것보다 늘어나는 것을 선호합니다. leading 및 trailing edge를 정렬하면 레이블이 모두 자연스럽게 가장 긴 레이블의 고유 콘텐츠 크기로 늘어납니다.

따라서 모든 레이블의 leading 및 trailing 가장자리를 정렬하기만 하면 됩니다. 또한 모든 텍스트 필드의 leading 및 trailing 가장자리를 정렬해야 합니다. 다행스럽게도 레이블의 앞 가장자리는 이미 슈퍼뷰의 앞 가장자리와 정렬되어 있습니다. 마찬가지로 텍스트 필드의 trailing 가장자리는 모두 수퍼뷰의 trailing 여백과 정렬됩니다. 다른 두 가장자리 중 하나를 정렬하면 됩니다. 모든 행의 너비가 같기 때문에 모든 것이 정렬됩니다.

이를 수행하는 방법에는 여러 가지가 있습니다. 이 예제의 경우 각 텍스트 필드에 동일한 너비를 지정합니다.

Dynamic Height Columns


이 예제는 동적 높이 레이블 및 텍스트 필드 레시피와 고정 높이 열 레시피에서 배운 모든 내용을 결합합니다. 이 예제의 목표는 다음과 같습니다.

  • 가장 긴 레이블의 길이를 기준으로 레이블의 trailing 엣지가 정렬됩니다.
  • 텍스트 필드의 너비는 동일하며 leading 및 trailing 엣지가 정렬됩니다.
  • 텍스트 필드가 확장되어 슈퍼뷰의 나머지 공간을 모두 채웁니다.
  • 행 사이의 높이는 행에서 가장 높은 요소를 기준으로 합니다.
  • 모든 것이 동적이므로 글꼴 크기나 레이블 텍스트가 변경되면 레이아웃이 자동으로 업데이트됩니다.
image11

Views and Constraints

고정 높이 열에서와 같이 레이블과 텍스트 필드를 배치합니다. 그러나 몇 가지 추가 제약 조건이 필요합니다.

image12
  1. First Name Label.Leading = Superview.LeadingMargin
  2. Middle Name Label.Leading = Superview.LeadingMargin
  3. Last Name Label.Leading = Superview.LeadingMargin
  4. First Name Text Field.Leading = First Name Label.Trailing + Standard
  5. Middle Name Text Field.Leading = Middle Name Label.Trailing + Standard
  6. Last Name Text Field.Leading = Last Name Label.Trailing + Standard
  7. First Name Text Field.Trailing = Superview.TrailingMargin
  8. Middle Name Text Field.Trailing = Superview.TrailingMargin
  9. Last Name Text Field.Trailing = Superview.TrailingMargin
  10. First Name Label.Baseline = First Name Text Field.Baseline
  11. Middle Name Label.Baseline = Middle Name Text Field.Baseline
  12. Last Name Label.Baseline = Last Name Text Field.Baseline
  13. First Name Text Field.Width = Middle Name Text Field.Width
  14. First Name Text Field.Width = Last Name Text Field.Width
  15. First Name Label.Top >= Top Layout Guide.Bottom + 20.0
  16. First Name Label.Top = Top Layout Guide.Bottom + 20.0 (Priority 249)
  17. First Name Text Field.Top >= Top Layout Guide.Bottom + 20.0
  18. First Name Text Field.Top = Top Layout Guide.Bottom + 20.0 (Priority 249)
  19. Middle Name Label.Top >= First Name Label.Bottom + Standard
  20. Middle Name Label.Top = First Name Label.Bottom + Standard (Priority 249)
  21. Middle Name Text Field.Top >= First Name Text Field.Bottom + Standard
  22. Middle Name Text Field.Top = First Name Text Field.Bottom + Standard (Priority 249)
  23. Last Name Label.Top >= Middle Name Label.Bottom + Standard
  24. Last Name Label.Top = Middle Name Label.Bottom + Standard (Priority 249)
  25. Last Name Text Field.Top >= Middle Name Text Field.Bottom + Standard
  26. Last Name Text Field.Top = Middle Name Text Field.Bottom + Standard (Priority 249)

Attributes

Attributes inspector에서 다음 속성을 설정합니다. 특히 모든 레이블의 텍스트를 오른쪽 정렬하십시오. 레이블을 오른쪽으로 정렬하면 텍스트보다 긴 레이블을 사용할 수 있으며 텍스트의 가장자리는 여전히 텍스트 필드 옆에 정렬됩니다.

image13

각 쌍에 대해 레이블의 콘텐츠 허깅은 텍스트 필드보다 높아야 합니다. 다시 말하지만 Interface Builder는 이 작업을 자동으로 수행해야 합니다. 그러나 크기 속성에서 이러한 우선 순위를 확인할 수 있습니다.

image14

Discussion

이 예제는 Dynamic Height Label and Text Field 및 Fixed Height Columns 예제에 설명된 기술을 단순히 결합합니다. 동적 높이 레이블 및 텍스트 필드 레시피와 마찬가지로 이 레시피는 제약 조건 쌍을 사용하여 행 사이의 세로 간격을 동적으로 설정합니다. 고정 높이 열 레시피와 마찬가지로 레이블에 오른쪽 정렬된 텍스트를 사용하고 열을 정렬하기 위해 명시적인 동일한 너비 제약 조건을 사용합니다.

NOTE

이 예에서는 뷰와 상단 레이아웃 가이드 사이의 거리에 20.0포인트 공간을 사용하고 옆의 뷰 사이에 8.0포인트 공간을 사용합니다. 고정된 20포인트 상단 여백을 설정하는 효과가 있습니다. 막대의 존재 여부에 따라 자동으로 조정되는 여백을 원하는 경우 추가 제약 조건을 추가해야 합니다. 일반적인 기술은 Adaptive Single View 예제에 나와 있습니다. 그러나 정확한 구현은 독자에게 과제로 남아 있습니다.

보시다시피 레이아웃의 논리가 다소 복잡해지기 시작했습니다. 그러나 일을 단순화할 수 있는 몇 가지 방법이 있습니다. 첫째, 앞서 언급한 것처럼 가능하면 스택 뷰를 사용해야 합니다. 또는 컨트롤을 그룹화한 다음 그룹을 배치할 수 있습니다. 이렇게 하면 하나의 복잡한 레이아웃을 더 작고 관리하기 쉬운 chunks로 나눌 수 있습니다.

Two Equal-Width Buttons


이 예제는 두 개의 동일한 크기의 버튼을 배치하는 방법을 보여줍니다. 수직으로 버튼은 화면 하단에 정렬됩니다. 사용 가능한 공간을 모두 채울 수 있도록 가로로 늘어납니다.

image15

Views and Constraints

Interface Builder에서 두 개의 버튼을 장면으로 드래그합니다. 장면 하단의 가이드라인을 사용하여 정렬합니다. 버튼의 너비를 동일하게 만드는 것에 대해 걱정하지 마십시오. 버튼 중 하나를 늘려 나머지 가로 공간을 채우십시오. 대략적인 위치를 잡은 후 다음 구속조건을 설정합니다. 자동 레이아웃은 올바른 최종 위치를 계산합니다.

image16
  1. Short Button.Leading = Superview.LeadingMargin
  2. Long Button.Leading = Short Button.Trailing + Standard
  3. Long Button.Trailing = Superview.TrailingMargin
  4. Bottom Layout Guide.Top = Short Button.Bottom + 20.0
  5. Bottom Layout Guide.Top = Long Button.Botton + 20.0
  6. Short Button.Width = Long Button.Width

Attributes

장치가 회전할 때 프레임이 어떻게 변경되는지 더 쉽게 볼 수 있도록 버튼에 눈에 보이는 배경색을 지정하십시오. 또한 버튼에 다른 길이의 제목을 사용하여 버튼 제목이 버튼의 너비에 영향을 미치지 않는다는 것을 보여줍니다.

image17

Discussion

이 예제는 버튼의 고유 높이를 사용하지만 레이아웃을 계산할 때 너비는 사용하지 않습니다. 수평으로 버튼은 너비가 동일하고 사용 가능한 공간을 채우도록 명시적으로 크기가 조정됩니다. 버튼의 고유 높이가 레이아웃에 어떤 영향을 미치는지 확인하려면 이 예제를 🔗 Two Equal-Width Views 예제와 비교하십시오. 이 레시피에는 수직 제약 조건이 4개가 아니라 2개뿐입니다.

또한 버튼의 텍스트가 레이아웃에 어떤 영향을 미치는지(또는 이 경우 영향을 주지 않음)를 설명하는 데 도움이 되도록 매우 다른 길이의 제목이 버튼에 제공됩니다.

NOTE

이 예제의 경우 버튼에 밝은 회색 배경색이 지정되어 프레임을 볼 수 있습니다. 일반적으로 버튼과 레이블은 배경이 투명하여 프레임의 변경 사항을 확인하기 어렵습니다(불가능하지는 않더라도).

Three Equal-Width Buttons


이 레시피는 Two Equal-Width Buttons 예제 확장하여 3개의 동일한 너비 버튼을 사용합니다.

image18

Views and Constraints

그림과 같이 버튼을 배치하고 제약 조건을 설정합니다.

image19
  1. Short Button.Leading = Superview.LeadingMargin
  2. Medium Button.Leading = Short Button.Trailing + Standard
  3. Long Button.Leading = Medium Button.Trailing + Standard
  4. Long Button.Trailing = Superview.TrailingMargin
  5. Bottom Layout Guide.Top = Short Button.Bottom + 20.0
  6. Bottom Layout Guide.Top = Medium Button.Bottom + 20.0
  7. Bottom Layout Guide.Top = Long Button.Bottom + 20.0
  8. Short Button.Width = Medium Button.Width
  9. Short Button.Width = Long Button.Width

Attributes

장치가 회전할 때 프레임이 어떻게 변경되는지 더 쉽게 볼 수 있도록 buttons에 눈에 보이는 배경색을 지정하십시오. 또한 버튼에 다른 길이의 제목을 사용하여 버튼 제목이 버튼의 너비에 영향을 미치지 않는다는 것을 보여줍니다.

image20

Discussion

추가 버튼을 추가하려면 3개의 추가 제약 조건(수평 제약 조건 2개 및 수직 제약 조건 1개)을 추가해야 합니다. 버튼 고유의 너비를 사용하지 않으므로 버튼의 위치와 크기를 모두 고유하게 지정하려면 최소 두 개의 수평 제약 조건이 필요합니다. 그러나 버튼의 고유 높이를 사용하고 있으므로 수직 위치를 지정하는 데 하나의 추가 제약 조건만 필요합니다.

NOTE

동일한 너비 제약 조건을 빠르게 설정하려면 세 개의 버튼을 모두 선택한 다음 Interface Builder의 핀 도구를 사용하여 동일한 너비 제약 조건을 만듭니다. Interface Builder는 필요한 제약 조건을 모두 자동으로 생성합니다.

Two Buttons with Equal Spacing


표면적으로 이 예제는 Two Equal-Width Buttons 예제와 유사합니다(스크린샷 참조). 그러나 이 레시피에서 버튼의 너비는 가장 긴 제목을 기준으로 합니다. 충분한 공간이 있는 경우 버튼은 둘 다 더 긴 버튼의 고유한 콘텐츠 크기와 일치할 때까지만 늘어납니다. 모든 추가 공간은 버튼 주위에 균등하게 나뉩니다.

image21

iPhone에서 2개의 동일 너비 버튼과 2개의 동일 간격 레이아웃 버튼은 세로 방향에서 거의 동일하게 나타납니다. 그 차이는 기기를 가로 방향으로 회전할 때만(또는 iPad와 같은 더 큰 기기를 사용할 때) 분명해집니다.

Views and Constraints

Interface Builder에서 두 개의 버튼과 세 개의 보기 개체를 끌어 배치합니다. 뷰 사이에 버튼을 배치한 다음 그림과 같이 제약 조건을 설정합니다.

image22
  1. Leading Dummy View.Leading = Superview.LeadingMargin
  2. Short Button.Leading = Leading Dummy View.Trailing
  3. Center Dummy View.Leading = Short Button.Trailing
  4. Long Button.Leading = Center Dummy View.Trailing
  5. Trailing Dummy View.Leading = Long Button.Trailing
  6. Trailing Dummy View.Trailing = Superview.TrailingMargin
  7. Bottom Layout Guide.Top = Leading Dummy View.Bottom + 20.0
  8. Bottom Layout Guide.Top = Short Button.Bottom + 20.0
  9. Bottom Layout Guide.Top = Center Dummy View.Bottom + 20.0
  10. Bottom Layout Guide.Top = Long Button.Bottom + 20.0
  11. Bottom Layout Guide.Top = Trailing Dummy View.Bottom + 20.0
  12. Short Button.Leading >= Superview.LeadingMargin
  13. Long Button.Leading >= Short Button.Trailing + Standard
  14. Superview.TrailingMargin >= Long Button.Trailing
  15. Leading Dummy View.Width = Center Dummy View.Width
  16. Leading Dummy View.Width = Trailing Dummy View.Width
  17. Short Button.Width = Long Button.Width
  18. Leading Dummy View.Height = 0.0
  19. Center Dummy View.Height = 0.0
  20. Trailing Dummy View.Height = 0.0

Attributes

장치가 회전할 때 프레임이 어떻게 변경되는지 더 쉽게 볼 수 있도록 버튼에 눈에 보이는 배경색을 지정하십시오. 또한 버튼에 다른 길이의 제목을 사용하십시오. 버튼은 가장 긴 제목을 기준으로 크기를 조정해야 합니다.

image23

Discussion

보시다시피 제약 조건 세트가 복잡해졌습니다. 이 예제는 특정 기술을 보여주기 위해 설계되었지만 실제 앱에서는 스택 뷰를 대신 사용하는 것을 고려해야 합니다.

이 예제에서는 수퍼뷰의 프레임이 변경됨에 따라 공백의 크기가 변경되기를 원합니다. 즉, 공백의 너비를 제어하려면 동일한 너비 제약 조건 세트가 필요합니다. 그러나 빈 공간에 제약 조건을 만들 수는 없습니다. 크기를 제한할 수 있는 일종의 개체가 있어야 합니다.

이 레시피에서는 더미 뷰를 사용하여 빈 공간을 나타냅니다. 이러한 뷰는 🔗 UIView 클래스의 빈 인스턴스입니다. 이 레시피에서는 뷰 계층 구조에 미치는 영향을 최소화하기 위해 0포인트 높이가 지정됩니다.

NOTE

더미 뷰는 레이아웃에 상당한 비용을 추가할 수 있으므로 신중하게 사용해야 합니다. 이러한 뷰가 크면 의미 있는 정보가 포함되어 있지 않더라도 그래픽 컨텍스트가 상당한 양의 메모리를 소비할 수 있습니다.

또한 이러한 뷰는 뷰 계층 구조의 responder chain에 참여합니다. 즉, hit testing와 같이 responder chain을 따라 전송되는 메시지에 응답합니다. 신중하게 처리하지 않으면 이러한 뷰는 이러한 메시지를 가로채고 응답하여 찾기 어려운 버그를 생성할 수 있습니다.

또는 🔗 UILayoutGuide 클래스의 인스턴스를 사용하여 공백을 나타낼 수 있습니다. 이 경량 클래스는 자동 레이아웃 제약 조건에 참여할 수 있는 직사각형 프레임을 나타냅니다. 레이아웃 가이드에는 그래픽 컨텍스트가 없으며 보기 계층 구조의 일부가 아닙니다. 따라서 레이아웃 가이드는 항목을 그룹화하거나 공백을 정의하는 데 이상적입니다.

불행하게도 Interface Builder에서는 scene에 레이아웃 가이드를 추가할 수 없으며 프로그래밍 방식으로 생성된 개체를 스토리보드 기반 장면과 혼합하면 상당히 복잡해질 수 있습니다. 일반적으로 사용자 정의 레이아웃 가이드를 사용하는 것보다 스토리보드와 Interface Builder를 사용하는 것이 좋습니다.

이 예제는 크거나 같은 제약 조건을 사용하여 버튼 주변의 최소 간격을 설정합니다. 또한 필수 제약 조건은 버튼의 너비가 항상 동일하고 더미 뷰도 항상 동일한 너비임을 보장합니다(버튼과 너비가 다를 수 있음). 나머지 레이아웃은 주로 버튼의 CHCR 우선 순위에 의해 관리됩니다. 공간이 충분하지 않으면 더미 보기가 0포인트 너비로 축소되고 버튼이 사용 가능한 공간을 그들 사이에 나눕니다(둘 사이의 표준 간격 사용). 사용 가능한 공간이 증가함에 따라 버튼은 더 큰 버튼의 고유 너비에 도달할 때까지 확장된 다음 더미 뷰가 확장되기 시작합니다. 더미 뷰가 계속 확장되어 나머지 공간을 채웁니다.

Two Buttons with Size Class-Based Layouts


이 예제는 두 가지 제약 조건 세트를 사용합니다. 하나는 Any-Any 레이아웃용으로 설치됩니다. 이러한 제약 조건은 🔗 Two Equal-Width Buttons 예제와 동일한 너비가 동일한 한 쌍의 버튼을 정의합니다.

다른 제약 세트는 Compact-Regular 레이아웃에 설치됩니다. 이러한 제약 조건은 아래와 같이 쌓인 버튼 쌍을 정의합니다.

image24

수직으로 쌓인 버튼은 iPhone에서 세로 방향으로 사용됩니다. 버튼의 수평 행은 다른 모든 곳에서 사용됩니다.

Constraints

두 개의 동일한 너비 버튼 예제에 대해 수행한 것과 똑같이 예제를 배치합니다. Any-Any 크기 클래스에서 제약 조건을 1~6으로 설정합니다.

다음으로 Interface Builder의 크기 클래스를 Compact-Regular 레이아웃으로 전환합니다.

image25

제약 조건 2와 제약 조건 5를 제거하고 그림과 같이 제약 조건 7, 8, 9를 추가합니다.

image26
  1. Short Button.Leading = Superview.LeadingMargin
  2. Long Button.Leading = Short Button.Trailing + Standard
  3. Long Button.Trailing = Superview.TrailingMargin
  4. Bottom Layout Guide.Top = Short Button.Bottom + 20.0
  5. Bottom Layout Guide.Top = Long Button.Botton + 20.0
  6. Short Button.Width = Long Button.Width
  7. Long Button.Leading = Superview.LeadingMargin
  8. Short Button.Trailing = Superview.TrailingMargin
  9. Long Button.Top = Short Button.Bottom + Standard

Attributes

장치가 회전할 때 프레임이 어떻게 변경되는지 더 쉽게 볼 수 있도록 단추에 눈에 보이는 배경색을 지정하십시오. 또한 버튼에 다른 길이의 제목을 사용하여 버튼 제목이 버튼의 너비에 영향을 미치지 않는다는 것을 보여줍니다.

image27

Discussion

Interface Builder를 사용하면 크기 클래스별 뷰, 뷰 속성 및 제약 조건을 설정할 수 있습니다. 너비와 높이 모두에 대해 세 가지 다른 크기 등급(Compact, Any 또는 Regular)에 대해 서로 다른 옵션을 지정하여 총 9개의 다른 크기 등급을 제공할 수 있습니다. 그 중 4개는 장치에서 사용되는 최종 크기 클래스(Compact-Compact, Compact-Regular, Regular-Compact 및 Regular-Regular)에 해당합니다. 나머지는 기본 크기 클래스 또는 둘 이상의 크기 클래스(Compact-Any, Regular-Any, Any-Compact, Any-Regular 및 Any-Any)의 추상 표현입니다.

지정된 크기 등급에 대한 레이아웃을 로드할 때 시스템은 해당 크기 등급에 대한 가장 구체적인 설정을 로드합니다. 즉, Any-Any 크기 클래스는 모든 보기에서 사용되는 기본값을 정의합니다. Compact-Any 설정은 너비가 좁은 모든 보기에 영향을 미치고 Compact-Regular 설정은 너비가 좁고 높이가 보통인 보기에만 사용됩니다. 보기의 크기 등급이 변경되면(예: iPhone이 세로에서 가로로 회전할 때) 시스템은 자동으로 레이아웃을 교체하고 변경 사항을 애니메이션으로 표시합니다.

이 기능을 사용하여 다른 iPhone 방향에 대해 다른 레이아웃을 만들 수 있습니다. 다른 iPad 및 iPhone 레이아웃을 만드는 데 사용할 수도 있습니다. 크기 클래스별 사용자 지정은 원하는 만큼 광범위하거나 간단할 수 있습니다. 물론 변경 사항이 많을수록 스토리보드가 더 복잡해지고 설계 및 유지 관리가 더 어려워집니다.

모든 기본 크기 클래스를 포함하여 가능한 각 크기 클래스에 대해 유효한 레이아웃이 있는지 확인해야 합니다. 일반적으로 하나의 레이아웃을 기본 레이아웃으로 선택하는 것이 일반적으로 가장 쉽습니다. Any-Any 크기 클래스에서 해당 레이아웃을 디자인합니다. 그런 다음 필요에 따라 최종 크기 등급을 수정합니다. 보다 구체적인 크기 클래스에서 항목을 추가하고 제거할 수 있음을 기억하십시오.

보다 복잡한 레이아웃의 경우 시작하기 전에 크기 클래스의 9 x 9 그리드를 그릴 수 있습니다. 해당 크기 클래스의 레이아웃으로 네 모서리를 채웁니다. 그런 다음 그리드를 통해 여러 크기 클래스에서 공유되는 제약 조건을 확인할 수 있으며 레이아웃과 크기 클래스의 최상의 조합을 찾는 데 도움이 됩니다.

크기 클래스 작업에 대한 자세한 내용은 🔗 Debugging Auto Layout을 참조하세요.