https://developer.apple.com/documentation/uikit/uistackview
UI StackView + 애플 개발자문서.
행 또는 열에 View들의 묶음을 배치할 수 있는 간소화된 인터페이스이다.
공식 문서의 설명
[개요]
StackView는 AutoLayout의 힘을 활용하여 사용자 인터페이스를 작성할 수 있게 해주며, 기기의 방향, 화면의 크기, 사용가능한 공간의 변경에 동적으로 적을할 수 있는 인터페이스를 생성한다.
글로된 설명은 언제나 어렵다.
카카오톡 대화창 TableView의 Cell이다.
그냥 View들을 배치할 수도 있지만, 만약 StackView를 사용한다면
StackView 안에 세로축으로 [(ImageView) + (발신자Label + 톡 내용 마지막줄Label) + (시간Label + 안읽은 메세지 수View)] 로 배치할 수 있다.
⭐️⭐️⭐️⭐️⭐️⭐️
그냥 배치하는것과 스택뷰에 넣어서 배치하는 것의 기준은 스택뷰에 들어가는 뷰가 런타임 도중 레이아웃이 바뀌느냐, 바뀌지 않느냐 이다.
추가로 앱의 레이아웃을 잡을 때는 무조건 StackView부터 쓰는게 좋다고 한다.
StackView로 해결할 수 없을 때만 직접 조건(Constarints)을 설정한다. 왜냐하면 스택뷰를 사용할 경우 복잡한 레이아웃에서 뷰를 추가하거나 삭제할 때 편하고 쉽게 관리할 수 있기 때문이다.
예시1 ) 동적인 레이아웃의 변화
예를 들어 "카톡 대화창에서 이미지뷰가 사라질 때 나머지 뷰들이 이미지뷰가 사라진 만큼 왼쪽으로 땡겨져야한다!" 라면 이미지의 유 무에 따라 오토레이아웃이 적용되어야 하므로 스택뷰에 넣어야 한다.
만약 이런 변화 없이 이미지뷰만 날아게가 한다! 라면 스택뷰를 쓰지 않아도 될 것이다.
예시2 ) 뷰를 추가하거나 삭제하는 경우
이런 복잡한 화면에 개발자도구와 열기 버튼 사이에 어떤 뷰를 끼워넣은 상황이 생긴다면?
할 수는 있지만 매우 귀찮고 오래걸릴 수 있다... 새로운 조건의 뷰를 하나하나 설정해줘야하며, 이미 잡혀있던 조건들도 모두 맞춰서 바꿔야한다. 혹은 원래 조건을 모두 지우고 새로운 조건을 추가해야할 수 있다.
이런 상황에 StackView는 진가를 발휘한다. StackView는 View를 추가하면 알아서 설정에 맞는 레이아웃을 잡아준다.
스택뷰의 오토레이아웃
스택뷰는 arrangedSubViews 속성에 포함된 모든 뷰의 레이아웃을 관리한다.
이러한 뷰들은 arrangedSubViews배열의 순서에 따라 스택뷰의 축(행, 열)을 따라 배치된다.
레이아웃의 정확한 모습은 스택뷰의 축(axis), 분배(distribution), 정렬(alignment), 간격(spacing) 및 기타 속성에 따라 다양하다.
뷰들은 arrangedSubViews배열의 순서에 따라 축을 따라 배치되며, 분배, 정렬, 간격 들을 이용해 뷰들의 Layout을 정해준다.
스택뷰는 subViews을 AutoLayout을 사용하지 않고 배치할 수 있지만,
스택 뷰 자체의 위치를 지정하기위해선 사용자가 AutoLayout을 직접 사용해야한다.
사용자는 StackView의 position과 size(옵션)를 정의해줘야한다. 그래야 StackView가 subViews의 레이아웃과 size(옵션)를 조정할 수 있다.
StackView의 position은 무조건 지정해주어야하며, 그 내부의 컨텐츠들의 사이즈까지 조정하려면 사이즈도 지정해야한다.
StackView의 AutoLayout
UIStackView.Axis(축)
StackView는 Stack의 Axis(축)의 각 Edges(가장자리)에 맞춰 Arranged View의 첫번째, 마지막 View를 배치한다.
- Horizontal stack(가로축의 스택뷰)에서는 첫번째 뷰의 왼쪽 엣지가 스택뷰의 왼쪽 엣지와 동일하게 배치됨을 의미하며,
마지막 뷰의 오른쪽 엣지가 스택뷰의 오른쪽 엣지와 동일하게 배치됨을 의미한다.
- Vertical stack(세로축 스택뷰)에서는 맨 위쪽 엣지와 맨 아래쪽 엣지가 스택뷰의 맨 위, 맨 아래 엣지와 동일하게 배치됨을 의미한다.
이게 무슨말이냐면..
1. axis = .Horizontal(가로방향)인 가로축 스택뷰인경우
- 첫번째 뷰의 왼쪽 Edge = StackView의 왼쪽 Edge
- 마지막 뷰의 오른쪽 Edge = StackView의 오른쪽 Edge
2. axis = .Vertical(세로방향)인 세로축 스택뷰인 경우
- 첫번째 뷰의 Top Edge = StackView의 Top Edge
- 마지막 뷰의 bottom Edge = StackView의 Bottom Edge
UIStackView.Distribution(분배)
UIStackView.Distribution.fillEqually 이외의 모든 분배(distribution)에 대해서는 스택뷰가 스택의 축을 따라 크기를 계산할 때 각 배열된 뷰의 intrincisContentSize속성을 사용한다.
UIStackView.Distribution.FillEqually분배는 모든 배열된 뷰의 크기를 동일하게 재조정하여 스택뷰를 축을 따라 채운다.
가능한 경우 스택뷰는 모든 배열된 뷰를 스택의 축에 수직으로 가장 큰 크기를 가진 뷰와 일치하도록 늘리기를 시도한다.
IntrincisContentSize = "고유한 컨텐츠 사이즈"
대부분의 View들은 Content크기에 맞게 따로 width, height을 지정하지 않아도 자동으로 autoLayout이 적용된다.
이유는 intrincisContentSize가 컨텐츠 크기에 맞게 사이즈를 계산해주기 때문이다.
따라서 StackView에서도 fillEqually를 제외하고는 ArrangeView들의 intrincisContentSize를 이용해 Axis에 따른 StackView의 사이즈를 계산해준다.
1) fill
StackView의 Axis(축)을 따라 가능한 공간을 모두 채우기 위해 Arrange view들의 사이즈를 재조정 하는 case
ㄱ. arrange views들이 StackView의 크기를 초과한다면 -> 각 뷰의 compression resistance priority에 따라 각 뷰의 크기를 감소시킨다.
ㄴ. arrange views들이 StackView의 크기에 미달한다면 -> 각 뷰의 hugging priority에 따라 각 뷰를 늘린다.
만약 모호한 점이 생긴다면, StackView는 arrangedSubViews 배열의 인덱스에 기초하여 각 뷰의 크기를 재조정한다.
- compression resistance priority
- 작아짐에 대한 저항
- 숫자가 클 수록 안작아질거야라는 "의지"가 강해짐
- hugging pritority
- 최대 크기에 대한 저항
- 숫자가 클수록 안늘어날거야 라는 "의지"가 강해짐
정리해보자면
StackView의 크기를 초과한다면 각 뷰의 compression resistance priority에 따라 제일 낮은 뷰의 크기부터 를 감소시킨다.
StackView의 크기에 모자란다면 각 뷰의 hugging priority에 따라 제일 낮은 뷰의 크기부터 증가시킨다.
2) fillEqually
StackView의 Axis(축)을 따라서 가능한 공간을 채우기 위해 ArrangedSubView들을 리사이징 한다.
뷰들은 StackView의 축을 따라 모두 같은 사이즈를 갖기위해 재조정된다.
축을 기준으로 Size를 재조정한다.
3) fillProportionally
StackView는 Axis에 따라 가능한 공간을 모두 채우기 위해 arrangedViews들을 리사이징한다.
뷰들은 그들의 intrinsic content size에 기초하여 비례적으로 사이즈를 재조정한다.
일단 StackView를 채우고 남은 공간이 생긴다면 intrinsic content size의 비율에 맞게 공간을 분배하여 resize된다.
남은 공간이 100이고 view 3개의 intrinsic content size의 비율이 2:5:3 이라면 20:50:30으로 분배되어 resize된다는 뜻 !
4) equalSpacing
StackView의 Axis(축)을 따라 가능한 공간을 채우기 위해 ArrangedSubView들의 위치를 재조정한다.
뷰들이 StackView를 채우기에 부족하다면 StackView는 뷰들 사이의 공간을 균일하도록 재배치한다.
뷰들이 StackView를 초과한다면, 뷰들의 compression resistance priority에 따라 뷰의 사이즈를 감소시킨다.
만약 모호함이 있다면, StackView는 arrangedsSubViews 배열의 인덱스에 따라 뷰들을 감소시킨다.
StackView 내부의 View들 사이의 공간을 균등하게 배치한다.
5) equalCentering
StackView의 Axis(축)에 따라 각 View들의 Center to Center의 거리를 동일하게 유지한다.
유지하는 간에 최소한 spacing프로퍼티의 값 만큼의 거리는 유지한다.
뷰들이 StackView의 크기를 초과한다면 spacing프로퍼티의 값 만큼 최소 거리가 될 때 까지 간격을 좁힌다.
그래도 StackView의 크기를 초과한다면 각 뷰들의 compression resistance priority를 비교하여 View의 크기를 감소시킨다.
그래도 모호함이 있다면 StackView는 arrangedSubViews들의 인덱스에 따라 뷰의 크기를 감소시킨다.
StackView.Alignment(정렬)
스택뷰가 어떻게 하위뷰들을 정렬할 것인지에 대한 내용이다.
1) fill
StackView의 Axis(축)에 따라 가능한 StackView의 공간을 채우기 위해 View들의 사이즈를 재조정한다.
- Horizontal인 경우 아래 위 공간을 fill하기 위해 늘린다
- Vertical인 경우 좌우 공간을 fill하기 위해 늘린다.
2) center
StackView가 축을 따라 View들의 center를 StackView의 Center에 맞춰 정렬한다.
3) leading
Vertical인 경우 StackView에서 View들의 Leading Edge와 StackView의 leading에 맞춰 정렬된다.
Horizontal인 경우 View들의 Top을 stackview의 Top에 맞추어 정렬한다.
4) trailing
Vertical인 경우 StackView에서 View들의 trailing Edge와 StackView의 trailing에 맞춰 정렬된다.
Horizontal인 경우 View들의 Bottom을 stackview의 Bottom에 맞추어 정렬한다.
5. top
Horizontal인 경우 View들의 top 이 stackview의 top에 맞추어 정렬한다.
Vertical인 경우 leading과 동일하다.
6. bottom
Horizontal인 경우 View들의 Bottom을 stackview의 Bottom에 맞추어 정렬한다.
Vertical인 경우 Trailing과 동일하다.
7. firstBaseline
firstBaseline을 기준으로 뷰를 정렬한다.
Horizontal을 위한 레이아웃이다.
8. lastBaseline
LastBaseline을 기준으로 정렬한다.
Horizontal을 위한 레이아웃이다.