SwiftUI 스택과 프레임
스위프트에는 버튼, 레이블, 슬라이더등 많은 뷰들이 존재한다 이 뷰들을 정렬하거나 크기를 정의하는데 사용하는 스택과 프레임을 사용한다
SwiftUI 스택
VStack(수직), HStack(수평), ZStack(중첩) 이렇게 3가지 스택 레이아웃이 있다 스택 내부에 하위 뷰들을 포함하도록 한다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Text("Data")
.font(.title)
HStack {
Text("Hello")
Text("SwiftUI")
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Good world!")
}
VStack {
Image(systemName: "person.crop.circle")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, World!")
}
}
}
.padding()
}
}
여기서 추가적으로 레이아웃을 정렬해야한다
Spacer, alignment, padding
뷰사이에 공간 추가를 위한 Spacer 컴포넌트 스택의 방향에 따라서 유연하게 확장/축소를 한다
스택의 정렬은 스택을 선얼할 때 스택에 정렬값을 지정하면 된다 VStack(alignment: .center)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import SwiftUI
struct ContentView: View {
var body: some View {
VStack(alignment: .center) {
Text("Data")
.font(.title)
HStack(alignment: .top) {
Text("Hello")
Text("SwiftUI")
Spacer()
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Good world!")
}
Spacer()
VStack(alignment: .leading, spacing: 15) { // spacing 간격 추가
Image(systemName: "person.crop.circle")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, World!")
}
}
}
.padding()
}
}
VStack 에서 사용할 수 있는 alignment
VStack은 세로로 뷰를 배치하는 스택으로, 가로 축의 정렬 옵션을 제공합니다
leading: 뷰를 왼쪽 정렬합니다.center: 뷰를 가운데 정렬합니다. (기본 값)trailing: 뷰를 오른쪽 정렬합니다.
HStack에서 사용할 수 있는 alignment
HStack은 가로로 뷰를 배치하는 스택으로, 세로 축의 정렬 옵션을 제공합니다
top: 뷰를 상단에 정렬합니다.center: 뷰를 수직 중앙에 정렬합니다. (기본 값)bottom: 뷰를 하단에 정렬합니다.firstTextBaseline: 텍스트 뷰들의 첫 번째 텍스트 기준선을 기준으로 정렬합니다.lastTextBaseline: 텍스트 뷰들의 마지막 텍스트 기준선을 기준으로 정렬합니다.
padding으로 간격 설정
padding(15) -> 전체 15간격
padding(.top, 10) -> 상단에만 10간격
뷰 그룹
여러개의 뷰를 한꺼번에 관리할려면 Group 를 사용한다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Group {
Text(" 1")
Text(" 2")
Text(" 3")
}
Group {
Text(" 1")
Text(" 2")
Text(" 3")
}
. font(.largeTitle)
}
}
}
텍스트 줄 제한과 레이아웃 우선순위
HStack은 text뷰를 한줄로 보여준다
1
2
3
4
5
6
7
8
9
10
11
12
import SwiftUI
struct ContentView: View {
var body: some View {
HStack{
Text("Hello, World1!")
Text("Hello, World2!")
Text("Hello, World3!")
}
}
}
여기서 길이를 초과하게 된다면
이렇게 자동으로 2줄로 표현된다 LineLimit()수정자를 사용시 출력 줄을 제한 할 수 있다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import SwiftUI
struct ContentView: View {
var body: some View {
HStack{
Text("Hello, World1!")
.lineLimit(1)//1줄만
Text("Hello, World2!")
.lineLimit(1...4) //1~4줄
Text("Hello, World3!")
Text("Hello, World4!")
}
}
}
여기서 우선순위를 지정한다면 layoutPriority() 해당부분의 뷰는 확실하게 보여줄 수 있다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import SwiftUI
struct ContentView: View {
var body: some View {
HStack{
Text("Hello, World1!")
Text("Hello, World2!")
.layoutPriority(1) // 우선 순위
Text("Hello, World3!")
Text("Hello, World4!")
Text("Hello, World5!")
Text("Hello, World6!")
}
}
}
SwiftUI 프레임
기본적으로 뷰는 자신의 콘텐츠에 따라서 크기가 자동으로 조절된다 여기서 크기를 지정하기 위해서 frame 수정자를 이용할 수 있다
1
2
3
4
5
6
7
8
9
10
11
12
13
import SwiftUI
struct ContentView: View {
var body: some View {
Text("Hello, World!")
.border(Color.red)
.frame(width: 50, height: .infinity)
Text("Hello, World!")
.border(Color.red)
.frame(minWidth: 10, maxWidth: 40)
}
}
프레임은 화면을 꽉 채울때 안전영역을 준수한다 안전영역으로 카메라 노치 부분과 시간 와이파이가 있는 상단부분이 포함된다 여기에도 확장하고 싶다면 edfesIgoningSafeArea() 수정자를 사용하면 된다
GeometryReader
프레임의 크기는 뷰들을 담고 있는 컨테이너의 크기에 따라 조절되도록 구성할 수 있다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import SwiftUI
struct ContentView: View {
var body: some View {
GeometryReader{ geometry in
VStack{
Text("Hello, World!")
.frame(width: geometry.size.width / 2, height: (geometry.size.height / 4) * 3) // VStack의 1/2폭과 3/4높이차지
.border(Color.blue)
.padding(1)
Text("Goodbye, World!")
.frame(width: geometry.size.width / 3, height: geometry.size.height / 4) //// VStack의 1/3폭과 1/4높이차지
.border(Color.green)
}
.border(Color.red)
}
}
}
스택 정렬
SwiftUI에서 HStack, VStack, ZStack 등의 스택 뷰는 정렬(alignment)을 통해 내부의 뷰들을 배치할 수 있다
1. leading
- 왼쪽 정렬 왼쪽을 기준으로 모든 뷰가 정렬
- 주로
HStack에서 사용하며, 왼쪽으로 모든 뷰를 정렬하고 싶을 때 사용
1
2
3
4
5
HStack(alignment: .top) {
Text("Hello")
Text("SwiftUI")
}
.frame(maxWidth: .infinity, alignment: .leading) // 왼쪽 정렬
2. trailing
- 오른쪽 정렬 오른쪽을 기준으로 모든 뷰가 정렬
- 주로
HStack에서 오른쪽 정렬을 할 때 사용
1
2
3
4
5
HStack(alignment: .top) {
Text("Hello")
Text("SwiftUI")
}
.frame(maxWidth: .infinity, alignment: .trailing) // 오른쪽 정렬
3. center
- 가운데 정렬 모든 뷰가 중앙에 배치
1
2
3
4
5
HStack(alignment: .center) {
Text("Hello")
Text("SwiftUI")
}
.frame(maxWidth: .infinity, alignment: .center) // 가운데 정렬
4. top
- 위쪽 정렬 주로
VStack에서 사용하며, 모든 뷰를 위쪽에 정렬
1
2
3
4
5
VStack(alignment: .leading) {
Text("Hello")
Text("SwiftUI")
}
.frame(maxHeight: .infinity, alignment: .top) // 위쪽 정렬
5. bottom
- 아래쪽 정렬 주로
VStack에서 사용하며, 모든 뷰를 아래쪽에 정렬
1
2
3
4
5
VStack(alignment: .leading) {
Text("Hello")
Text("SwiftUI")
}
.frame(maxHeight: .infinity, alignment: .bottom) // 아래쪽 정렬
6. firstTextBaseline
- 텍스트의 첫 번째 기준선을 따라 정렬
- 주로
HStack에서 텍스트의 첫 번째 줄을 맞춰 정렬할 때 사용
1
2
3
4
HStack(alignment: .firstTextBaseline) {
Text("Hello")
Text("SwiftUI")
}
7. lastTextBaseline
- 텍스트의 마지막 기준선을 따라 정렬
- 주로
HStack에서 텍스트의 마지막 줄을 맞춰 정렬할 때 사용
1
2
3
4
HStack(alignment: .lastTextBaseline) {
Text("Hello")
Text("SwiftUI")
}
8. topLeading, topTrailing, bottomLeading, bottomTrailing
ZStack에서 사용할 수 있는 복합적인 정렬 옵션 두 축의 정렬을 동시에 설정하여 원하는 위치에 뷰를 배치- 예를 들어,
topLeading은 왼쪽 상단,bottomTrailing은 오른쪽 하단에 정렬
1
2
3
4
ZStack(alignment: .topLeading) {
Color.red.frame(width: 100, height: 100)
Text("Hello").foregroundColor(.white)
}