BOID

[SwiftUI] SwiftUI에서 스택으로 레이아웃 잡기 본문

swiftUI시작기

[SwiftUI] SwiftUI에서 스택으로 레이아웃 잡기

HoonIOS 2022. 3. 20. 16:55

안녕하세요, HoonIOS입니다. :)

SwiftUI에서 뷰의 레이아웃을 잡아주는 다양한 방법이 있는데 이번 포스팅에는 스택을 이용해 레이아웃을 잡는 방법에 대해 살펴보겠습니다.

 

 스택

스택은 실제로 Storyboard, UIKit에서 사용하는 레이아웃입니다. 바로 UIStackView인데요, 실제로 SwiftUI에서 스택도 같은 역할을 한다고 생각하시면 더 이해하기 쉬울 수 있습니다.

 

Storyboard를 사용해서 레이아웃을 구성할때는 굳이 UIStackView을 필수적으로 사용할 필요 없이 다른 방법을 이용해서도 구현을 할 수 있었는데요, SwiftUI에서는 거의 필연적(?)이라 매우 중요합니다. 

 

 스택의 특성

스택은 Content를 제네릭 매개 변수로 받아 자식 뷰로 표현하는 제네릭 구조체로 선언되어 있습니다. 스택을 사용하면 콘텐츠로 전달 받은 자식 뷰들을 특정 방식으로 표현하는 하나의 새로운 뷰가 만들어집니다.

struct HStack<Contents> : View where Content: View
struct VStack<Contents> : View where Content: View
struct ZStack<Contents> : View where Content: View

하나의 some View에 여러개의 view를 반환하는 구조체를 사용하면 컴파일 오류가 발생하게 됩니다.

무슨 말이냐구요?

 

아래와 같이 연속적으로 텍스트를 작성하면 컴파일 오류가 발생한다는 것입니다. 그 이유는 하나의  뷰에 여러 개의 뷰를 반환시켰기 때문이죠?

var body: some View {
	Text("SwiftUI")
	Text("HoonIOS")
}

 

이럴 경우 두 개의 Text를 하나의 컨테이너 뷰로 묶어줘야 합니다. 바로 스택으로 묶어주는 거죠

 

var body: some View {
    HStack {
        Text("SwiftUI")
        Text("HoonIOS")
    }
}

* 컨테이너 뷰를 사용하는 방법

컨테이너 뷰 {
     ~~~
     ~~~
}

 

 스택의 종류

  1. Horizontal Stack(HStack) - 가로방향으로 뷰를 배열
  2. Vertical Stack(VStack) - 세로 방향으로 뷰를 배열
  3. Depth Stack(ZStack) - 층으로, 겹겹이 뷰를 배열

 Horizontal Stack (HStack)

가로방향으로 뷰를 쌓아가면서 표현하는 Stack

 

HStack {
    Rectangle()
        .fill(Color.blue)
        .frame(width: 100, height: 100)
    Rectangle()
        .fill(Color.yellow)
        .frame(width:100, height: 100)
    }

HStack

 Vertical Stack (VStack)

세로 방향으로 뷰를 쌓아가면 표현하는 Stack

VStack {
    Rectangle()
        .fill(Color.blue)
        .frame(width: 100, height: 100)
    Rectangle()
        .fill(Color.yellow)
        .frame(width:100, height: 100)
}

VStack

 

 Depth Stack (ZStack)

겹겹히 층으로 뷰를 쌓아가면 표현하는 스택

무슨 말인지 글만 보고 이해하기 어려우실 수 있습니다. 아래 예시로 한번 확인해보겠습니다.

ZStack {
    Rectangle()
        .fill(Color.blue)
        .frame(width: 150, height: 150)
    Rectangle()
        .fill(Color.yellow)
        .frame(width: 100, height: 100)
    Circle()
        .fill(Color.black)
        .frame(width: 50, height: 50)
}

ZStack

위 코드를 보시면 두 개의 사각형과 한 개의 원을 다른 색깔로 배치한 것을 볼 수 있습니다. 

또 frame 크기를 다르게 줘 맨 아래에 있는 파란색 사각형 그 위에 노란색 사각형 그위에 검은색 타원형을 배치한것을 볼수 있습니다.  위 예시로 봤듯이 층별로 그위에 덮어져서 그려지는 것을 알 수 있으실 겁니다.

 

좀 더 확고하게 확인을 해보시려면 단순히 frame으로 크기를 줄이는 게 아니라 offset 수식어를 이용해 도형 위치를 이동시켜서 확인해 보시는 걸 추천드려요 :) 

 

 스택의 기본 생성자 (init)

스택의 기본 생성자로는 3개를 받고 있는데 뷰의 정렬을 위한 alignment, 뷰간의 간격을 지정하는 spacing, 콘텐츠로 표시할 Content를 받고 있습니다.

 

각 기본값은 alignment -> .center 중앙 정렬, spacing -> nil nil인 경우 뷰에 따라 다른 기본값을 적용, Content -> 표시될  Content입니다.

 

이제 각 수식어들을 살펴볼까요? 

 

 spacing

뷰간의 간격인데요 spacing 값을 지정하면 원하는 만큼 간격을 떨어트릴 수 있습니다.

 

HStack(spacing: 30) { ... }
HStack(spacing: 100) { ... }

 

Alignment

정렬을 의미하는 것으로 뷰의 위치를 정렬하는 것을 의미합니다.

 

HStack(alignment: .top, spacing: 30) {
    Rectangle()
        .fill(Color.blue)
        .frame(width: 50, height: 50)
    Rectangle()
        .fill(Color.yellow)
        .frame(width: 50, height: 100)
    Rectangle()
        .fill(Color.red)
        .frame(width: 50, height: 150)
}

.top

.bottom

 

 

Stack을 통해 다양한 뷰를 쉽게 그릴 수 있으므로 활용하면 좋을 것 같습니다.

 

다음에는 Spacer을 통해 뷰를 배치하는 법에 대해 알아보겠습니다.

반응형
Comments