https://developer.apple.com/documentation/uikit/uistackview
"A streamlined interface for laying out a collection of views in either a column or a row."
열 혹은 행에 뷰의 컬렉션을 배치하기 위한 간단한 인터페이스입니다.
@MainActor class UIStackView : UIView
스택 뷰는 사용 가능한 공간에서 기기의 orientation, 스크린 크기, 기타 모든 변경사항에 동적으로 적응할 수 있는 UI를 생성하면서 오토 레이아웃의 강력함을 극대화해줍니다. 스택 뷰는 자신의 arrangedSubviews
속성에 있는 모든 뷰의 레이아웃을 관리합니다. 이러한 뷰들은 arrangedSubviews
배열에서 순서에 기반해 스택 뷰의 축을 따라 정렬됩니다. 정확한 레이아웃은 스택 뷰의 축, 배분, 정렬, 공간, 기타 속성에 따라 다양합니다.
스택 뷰를 사용하려면 편집하고자 하는 스토리보드를 열어야 합니다. 객체 라이브러리에서 수평 스택 뷰 혹은 수직 스택 뷰를 드래그하고, 원하는 곳으로 스택 뷰를 위치시켜야 합니다. 다음으로 스택의 컨텐트를 드래그하고, 스택에 뷰 혹은 컨트롤을 드롭해야 합니다. 필요할 때마다 뷰 및 컨트롤을 스택에 계속 추가할 수 있습니다. 인터페이스 빌더는 스택의 컨텐트에 기반해 스택의 크기를 조절합니다. 특성 인스펙터에서 스택 뷰의 속성을 수정해서 스택 컨텐트의 모양을 조정할 수도 있습니다.
Note
위치를 정의해야 하며, (선택적으로) 스택 뷰의 크기도 정의해야 합니다. 이후 스택 뷰는 레이아웃과 컨텐트 크기를 관리할 수 있습니다.
스택 뷰는 자신의 정렬된 뷰를 위치시키고 크기를 조절하기 위해 오토 레이아웃을 사용합니다. 스택 뷰는 스택의 축에 따라 자신의 edge로 첫 번째와 마지막 정렬된 뷰를 정렬합니다. 수평 스택에서 첫 번째로 정렬된 뷰의 leading edge는 스택의 leading edge에 고정되고, 마지막으로 정렬된 뷰의 trailing edge는 스택의 trailing edge에 고정됩니다. 수직 스택에서 top, bottom edge는 각각 스택의 top, bottom edge에 고정됩니다. 스택 뷰의 isLayoutMarginsRelativeArrangement
속성을 true
로 설정하면 스택 뷰는 컨텐트를 edge 대신 관련 마진에 고정합니다.
UIStackView.Distribution.fillEqually
배분을 제외한 모든 배분의 경우 스택 뷰는 스택의 축을 따라 스택의 크기를 계산할 때, 각 정렬된 뷰의 intrinsicContentSize
속성을 사용합니다. UIStackView.Distribution.fillEqually
는 스택 뷰의 축에 따라 스택 뷰를 채우면서 모든 정렬된 뷰 크기를 다시 조절합니다. 그렇기 때문에 정렬된 뷰는 크기가 같습니다. 가능한 경우 스택 뷰는 스택의 축에 따라가는 가장 긴 내적 크기에 뷰를 일치시키기 위해 모든 정렬된 뷰를 확장시킵니다.
UIStackView.Alignment.fill
정렬을 제외한 모든 정렬에서 스택 뷰는 스택의 축에 수직인 크기를 계산할 때 각각의 정렬된 뷰의 intrinsicContentSize
속성을 사용합니다. UIStackView.Alignment.fill
은 스택 뷰의 축에 수직으로 스택 뷰를 채우기 위해 모든 정렬된 뷰의 크기를 조절합니다. 가능한 경우 스택 뷰는 스택의 축에 수직인 가장 긴 내적 크기에 뷰를 일치시키기 위해 모든 정렬된 뷰를 확장시킵니다.
스택 뷰가 오토 레이아웃을 직접 사용하지 않고 컨텐츠에 대한 레이아웃을 설정할지라도 스택 뷰 자체의 위치에 대한 오토 레이아웃 사용은 필요합니다. 일반적으로 스택 뷰의 위치를 정의하기 위해 적어도 스택 뷰의 두 인접 edge를 고정해야 함을 의미합니다. 추가적인 제약 없이 시스템은 컨텐츠에 기반해 스택 뷰의 크기를 계산합니다.
isLayoutMarginsRelativeArrangement
속성이 true
로 설정되는 경우 스택 뷰의 fitting 크기는 마진에 대한 공간을 포함하기 위해 증가합니다.스택 뷰의 높이, 넓이, 혹은 모두를 구체화하기 위해 추가적인 제약을 제공할 수 있습니다. 이 경우 스택 뷰는 레이아웃과 구체화된 영역을 채우기 위한 정렬된 뷰의 크기를 조정합니다. 정확한 레이아웃은 스택 뷰의 속성에 기반해 달라집니다. 스택 뷰가 컨텐트에 대해 추가적인 공간 혹은 불충분한 공간을 갖는 것을 처리하는 방법에 대해서 완전한 설명을 보려면 UIStackView.Distribution
및 UIStackView.Alignment
열거형을 보시기 바랍니다.
top, bottom, centery Y 위치 대신 첫 번째 혹은 마지막 베이스라인에 기반해 스택 뷰를 위치시킬 수도 있습니다. 스택 뷰의 fitting 크기처럼 이러한 베이스라인은 스택 뷰의 컨텐트에 기반해 계산됩니다.
forFirstBaselineLayout
, forLastBaselineLayout
메소드에서 가장 큰 뷰를 반환합니다. 가장 큰 뷰도 스택 뷰인 경우 중첩된 스택 뷰에서 forFirstBaselineLayout
혹은 forLastBaselineLayout
호출의 결과를 반환합니다.forFirstBaselineLayout
에 대한 첫 번째 정렬된 뷰를 반환하고, forLastBaselineLayout
에 대한 마지막 정렬된 뷰를 반환합니다. 이와 같은 뷰 역시 스택 뷰인 경우 중첩된 스택 뷰에서 forFirstBaselineLayout
혹은 forLastBaselineLayout
호출의 결과를 반환합니다.Note
베이스라인 정렬은 높이가 컨텐트 크기의 높이와 일치하는 뷰에 대해서만 동작합니다. 뷰가 확장되거나 수축되면 베이스라인은 잘못된 위치에서 나타납니다.
스택 뷰를 사용해 컨텐트를 배치하는 일반적인 접근방식은 아래와 같습니다.
위치만 정의합니다. 슈퍼뷰에 인접 edge 둘을 고정해서 스택 뷰의 위치를 정의할 수 있습니다. 이 경우 스택 뷰는 정렬된 뷰에 기반해 두 차원에서 자유롭게 크기가 늘어납니다. 이 접근방식은 스택 뷰의 컨텐트가 내적 컨텐트 크기에서 나타나길 원할 때 특히 유용하며, 스택 뷰에 상대적으로 다른 UI 요소들을 정렬하길 원할 때에도 유용합니다.
Figure 3은 스택 뷰의 leading과 top edge가 슈퍼뷰에 고정된 스택 뷰를 보여주고 있습니다. 레이블은 8 포인트 공간을 갖고 첫 번째 베이스라인으로 정렬되고, 슈퍼뷰에서 스택 뷰의 컨텐트를 왼쪽 정렬하고 있습니다.
스택의 축을 따라 스택의 크기를 정의합니다. 이 경우 스택 뷰의 크기를 해당 차원에서 정의하면서, 슈퍼뷰로 축을 따라 스택의 edge 모두를 고정합니다. 스택 뷰의 위치를 정의하기 위해 다른 edge 중 한 가지를 고정할 필요가 있습니다. 스택 뷰는 정의된 공간을 채우기 위해 축을 따라 컨텐트의 크기 및 위치를 정의합니다. 그러나 고정되지 않은 edge는 자유롭게 움직이며, 가장 큰 정렬된 뷰의 크기에 기반합니다.
Figure 4는 슈퍼뷰에 고정된 leading, top, trailing edge를 갖는 스택 뷰를 보여줍니다. fill distribution을 사용하면 컨텐트가 뷰의 넓이를 채우기 위해 크기가 조절되고, 텍스트 필드는 레이블보다 낮은 content hugging 운선순위를 갖고 있기 때문에 필요할 때 확장됩니다.
스택의 크기를 축에 수직이도록 정의합니다. 이 접근방식은 이전 예시와 유사하지만, 스택 뷰의 축에 두 개의 edge를 수직으로 고정시키고, 하나의 edge는 축을 따라 고정합니다. 이 접근방식은 스택 뷰에 정렬된 뷰를 추가하고 제거할 때 축에 따라 스택 뷰가 늘어나고 줄어들도록 해줍니다. fillEqually
distribution을 사용하지 않는 한 정렬된 뷰는 스스로의 내적 컨텐트 크기에 따라 크기가 정해집니다. 축에 수직으로 뷰는 스택 뷰의 정렬에 기반해 정의된 공간에서 배치됩니다.
Figure 5는 네 개의 레이블과 하나의 버튼을 포함하고 있는 수직 스택을 보여주고 있습니다. 스택은 8.0 포인트 공간과 중앙 정렬을 사용합니다. 스택 뷰의 높이는 아이템이 스택에 추가되거나 스택으로부터 제거될 때 늘어나거나 줄어들 것입니다.
스택 뷰의 크기와 위치를 정의합니다. 이 경우 스택 뷰의 모든 네 edge를 고정시키며, 스택 뷰는 제공된 공간 내에 컨텐트를 위치시키게 됩니다.
Figure 6은 슈퍼뷰에 네 개의 모든 edge가 고정된 수직 스택 뷰를 보여주고 있습니다. 중앙 정렬 및 fill distribution을 사용함으로써 스택 뷰는 스택 뷰의 컨텐트가 수평 및 수직 중앙으로 스크린을 채우도록 합니다. 그러나 이 접근방식으로 바람직한 레이아웃을 가져오는 것은 추가적인 단계가 필요합니다. 기본값으로 스택 뷰는 수직으로 레이블을 확장시키고 이미지 뷰를 확장시키지는 않습니다. 이미지 뷰 크기를 조절하려면 레이블의 컨텐트 hugging 우선순위 아래로 이미지 뷰의 컨텐트 hugging 우선순위를 낮춰야 합니다. 추가적으로 이미지 뷰의 크기 조절로 이미지 뷰의 aspect ratio를 유지하려면 모드를 Aspect Fit
으로 설정해야 합니다. 이미지 뷰와 스택 뷰 사이에 동일한 넓이 제약을 추가하는 것은 이미지가 사용 가능한 공간을 채울 수 있도록 해줄 것입니다.
스택 뷰는 자신의 정렬된 뷰 위치 및 크기를 관리합니다. 스택 뷰가 자신의 컨텐트를 위치시키는 방법을 정의하는 몇 가지 속성이 있습니다.
isBaselineRelativeArrangement
속성은 뷰 사이의 수직 공간이 베이스라인으로부터 계산되는지 여부를 결정합니다.isLayoutMarginsRelativeArrangement
속성은 스택 뷰가 레이아웃 마진에 상대적으로 정렬된 뷰를 배치할지 여부를 결정합니다.보통 아이템의 적은 수를 배치하기 위해 하나의 스택 뷰를 사용할 것입니다. 다른 스택 뷰 내부에 스택 뷰를 중첩시켜서 더 복잡한 뷰 계층구조를 빌드할 수 있습니다. 예를 들어 Figure 7은 두 개의 수평 스택 뷰를 포함하고 있는 하나의 수직 스택 뷰를 보여주고 있습니다. 각각의 수평 스택 뷰는 레이블과 텍스트 필드를 포함하고 있습니다.
정렬된 뷰에 추가적인 제약을 추가해서 정렬된 뷰의 모양을 조정할 수도 있습니다. 예를 들어 뷰에 대한 최소 혹은 최대 높이, 넓이를 설정하기 위해 제약을 사용할 수 있습니다. 뷰에 대한 aspect ratio 또한 정의할 수 있습니다. 스택 뷰는 컨텐트를 배치시킬 때 이와 같은 제약을 사용합니다. 예를 들어 이미지 뷰에는 이미지 크기가 조절될 때 상수 aspect ratio를 강제하는 aspect ratio 제약을 갖고 있습니다.
Note
스택 뷰 내부에서 뷰에 대한 제약을 추가할 때 충돌을 피하도록 신중하시기 바랍니다. 일반적으로 주어진 차원에서 뷰의 크기가 내적 컨텐트 크기로 돌아가는 경우 해당 차원에 대한 제약을 안전하게 추가할 수 있습니다.
스택 뷰는 자신의 arrangedSubviews
속성이 항상 하위뷰 속성의 하위집합이도록 합니다. 구체적으로 스택 뷰는 아래 규칙을 강제합니다.
arrangedSubviews
배열에 뷰를 추가할 때, 해당 뷰가 하위뷰가 아니라면 이 뷰를 하위뷰로 추가합니다.arrangedSubviews
배열에서도 제거합니다.arrangedSubviews
배열로부터 뷰를 제거하는 것은 하위뷰로 제거하지는 않습니다. 스택 뷰가 더 이상 뷰의 크기 및 위치를 관리하지 않지만, 뷰는 여전히 뷰 계층구조의 부분이며, 시각화될 수 있는 경우 스크린에 렌더링됩니다.arrangedSubviews
배열이 항상 하위뷰 배열의 하위집합을 포함할지라도 해당 배열의 순서는 독립적으로 남습니다.
arrangedSubviews
배열의 순서는 스택에서 나타나는 뷰의 순서를 결정합니다. 수평 스택에서 뷰는 읽는 방향 순서로 배치되고, 낮은 인덱스 뷰가 높은 인덱스에 먼저 나타납니다. 예를 들어 영어에서 뷰는 왼쪽부터 오른쪽 방향으로 배치됩니다. 수직 스택의 경우 뷰는 낮은 인덱스 뷰가 높은 인덱스 뷰보다 위에 위치하면서 상단부터 하단으로 뷰가 배치됩니다.스택뷰는 뷰가 arrangedSubviews
배열에서 추가, 제거, 삽입될 때마다 레이아웃을 자동으로 업데이트합니다. 혹은 정렬된 하위뷰의 isHidden
속성이 변경될 때마다 레이아웃을 자동으로 업데이트하기도 합니다.
// Appears to remove the first arranged view from the stack.
// The view is still inside the stack, it's just no longer visible, and no longer contributes to the layout.
let firstView = stackView.arrangedSubviews[0]
firstView.isHidden = true
The stack view also automatically responds to changes to any of its properties. For example, you can dynamically change the stack’s orientation, by updating the stack view’s axis property.
// Toggle between a vertical and horizontal stack
if stackView.axis == .Horizontal {
stackView.axis = .Vertical
}
else {
stackView.axis = .Horizontal
}
You can animate both changes to the arranged subview’s isHidden property and changes to the stack view’s properties by placing these changes inside an animation block.
// Animates removing the first item in the stack.
UIView.animateWithDuration(0.25) { () -> Void in
let firstView = stackView.arrangedSubviews[0]
firstView.isHidden = true
}
마지막으로 인터페이스 빌더에서 스택 뷰 속성의 여러 가지에 대해 사이즈 클래스의 특정 값을 정의할 수 있습니다. 시스템은 스택 뷰의 크기 클래스가 변경될 때마다 이러한 변경사항을 자동으로 애니메이션 처리합니다.
설정 가능하고 고수준으로 커스터마이징 가능한 레이아웃을 사용해서 중첩된 뷰를 표시합니다.
https://developer.apple.com/documentation/uikit/views_and_controls/collection_views
https://velog.io/@panther222128/Collection-Views
커스터마이징 가능한 행들로 구성된 하나의 열에 데이터를 표시합니다.
https://developer.apple.com/documentation/uikit/views_and_controls/table_views
https://velog.io/@panther222128/Table-Views
포함된 뷰의 스크롤링 및 확대, 축소를 허용하는 뷰입니다.
https://developer.apple.com/documentation/uikit/uiscrollview
https://velog.io/@panther222128/UIScrollView