본문 바로가기
2023년 이전/iOS

SwiftUI - 스택과 프레임

by JeongUPark 2020. 10. 4.
반응형

다음 내용들은 [핵심만 골라배우는 SwiftUI 기반 iOS 프로그래밍] 을 공부하면서 정리한 내용 입니다.

뷰를 공부할 때 뷰들을 추가하기 위해 다양한 컨테이너들이 있었고 그중에 스택 컨테이너가 있었습니다. (VStack, HStack, ZStack) 

이번에는 이 Stack과 프레임의 개념에 대하여 설명해 보겠습니다.

 

1. SwiftUI 스택

SwiftUI에는 VStack(수직) , HStack(수평) , ZStack(중첩) 3개의 Stack 레이아웃 뷰가 있습니다.

VStack

struct ContentView: View {
    
    var body: some View {
        VStack{
            Image(systemName: "goforward.10")
            Image(systemName: "goforward.15")
            Image(systemName: "goforward.30")
        }
    }
}

HStack

struct ContentView: View {
    
    var body: some View {
        HStack{
            Image(systemName: "goforward.10")
            Image(systemName: "goforward.15")
            Image(systemName: "goforward.30")
        }
    }
}

ZStack

struct ContentView: View {
    
    var body: some View {
        ZStack{
            Image(systemName: "goforward.10")
            Image(systemName: "goforward.15")
            Image(systemName: "goforward.30")
        }
    }
}

그리고 위 스택들을 커멘트키를 누르고 클릭하면 나오는 다음 메뉴들을 통하여

HStack 이나 VStack 또는 Lsit에 포함 시킬 수 있습니다.

 

2.Spacer, alignment, padding

Spacer 는 배치된 뷰들의 간격을 제공하기 위해 스텍의 방향에 따라 확장 축소 됩니다.

import SwiftUI

struct ContentView: View {
    
    var body: some View {
        
        VStack{
            Image(systemName: "goforward.10")
            Spacer()
            Image(systemName: "goforward.15")

        }.frame(width: 200, height: 200, alignment: .center)
    }
}

이렇게 하면

이미지 사이에 세로로 공간이 생기고

import SwiftUI

struct ContentView: View {
    
    var body: some View {
        
        HStack{
            Image(systemName: "goforward.10")
            Spacer()
            Image(systemName: "goforward.15")

        }.frame(width: 200, height: 200, alignment: .center)
    }
}

이렇게 하면

이미지 사이에 가로로 간격이 생성 됩니다.

alignment 은 정렬 방식을 말합니다.

import SwiftUI

struct ContentView: View {
    
    var body: some View {
        
        VStack(alignment: .center, spacing: 15)
        {
            Text("Financial Results").font(.title)
            Text("Financial").font(.title)
        }
        
    }
}

이렇게 하면 간격이 15고 가운데 정렬이 됩니다.

alignment 를 .leading으로 바꾸면 좌측정렬이 됩니다.

struct ContentView: View {
    
    var body: some View {
        
        VStack(alignment: .leading, spacing: 15)
        {
            Text("Financial Results").font(.title)
            Text("Financial").font(.title)
        }
        
    }
}

alignment를 .trailing으로 바꾸면 우측정렬이 됩니다.

import SwiftUI

struct ContentView: View {
    
    var body: some View {
        
        VStack(alignment: .trailing, spacing: 15)
        {
            Text("Financial Results").font(.title)
            Text("Financial").font(.title)
        }
        
    }
}

그리고 padding을 줘서 직접 뷰에 간격을 줄 수 도 있습니다.

Text("Financial Results").font(.title).padding()

그리고 padding에 값을 주어 그 크기만큼 간격을 줄 수 있고

Text("Financial Results").font(.title).padding(10)

방향을 주어서 그 방향에만 간격을 줄 수 도 있습니다.

Text("Financial Results").font(.title).padding(.top, 10)

 

3. 컨테이너 뷰의 자식 제한

컨테이너 뷰의 자식은 총 10개 까지만 가능합니다. 그리래서 10개 이상의 자식을 추가 하면 Extra argument in call 를 error를 볼 수 있습니다.

만일 컨테이너 뷰 안에 10개 이상의 뷰를 넣어야 한다면

import SwiftUI

struct ContentView: View {
    
    var body: some View {
        
        VStack(alignment: .trailing, spacing: 15)
        {
            Group{
                Text("Financial Results").font(.title).padding(.top, 10)
                Text("Financial").font(.title)
                Text("Financial").font(.title)
                Text("Financial").font(.title)
                Text("Financial").font(.title)
                Text("Financial").font(.title)
            }
            Group{
                Text("Financial").font(.title)
                Text("Financial").font(.title)
                Text("Financial").font(.title)
                Text("Financial").font(.title)
                Text("Financial").font(.title)
                Text("Financial").font(.title)
            }
            
        }
        
    }
}

이렇게 그룹으로 묶어서 뷰 작업을 수행하면 됩니다.

 

4.텍스트 줄 제한과 레이아웃 우선순위

HStack 뷰는 Text를 한줄로 보여줍니다.

        HStack{
            Image(systemName: "airplane")
            Text("Flight times: ")
            Text("London")
        }.font(.largeTitle)

이렇게 작성을 하면, 공간이 충분할 경우 한줄로 잘 보이게 됩니다.

그런데 공간이 부족하면

이렇게 2줄이 될 수 있습니다.

만일 2줄이 되면 안되고 1줄을 유지해야 한다면

        HStack{
            Image(systemName: "airplane")
            Text("Flight times: ")
            Text("London")
        }.font(.largeTitle).lineLimit(1)

lineLimit로 줄 제한을 줄 수 있습니다. 이렇게 제한을 주면

이렇게 글자들이 줄어 듭니다. 만일 일부 글자를 다 보여줘야하는 상황이라면 그 Text에 layoutPriority를 주어

        HStack{
            Image(systemName: "airplane")
            Text("Flight times: ")
            Text("London").layoutPriority(1)
        }.font(.largeTitle).lineLimit(1)

우선 순위를 주면

이렇게 우선 순위를 준 Text는 줄임없이 나타나게 됩니다.

 

4. 프레임

뷰는 자신의 콘텐트와 자신이 속한 레이아웃에 따라 자동으로 크기가 조절됩니다. 하지만 frame 수정자를 사용하여 뷰의 크기나 영역을 조절 할 수 있습니다.

  .frame(width: 100, height: 100, alignment: .center)

프레임은 위와 같이 가로 세로 그리고 정렬을 지정할 수 있으며,

frame(minWidth: 0, idealWidth: 100, maxWidth: .infinity,
minHeight: 0, idealHeight: 100, maxHeight: .infinity, alignment: .center)

최소 넓이, 이상적인 넓이, 최대 넓이, 최소 높이, 이상적이 높이 최대 높이, 정렬 방식을 정할 수 있습니다. (여기서 .infinity는 말그대로 무한대를 의미합니다.)

 

디폴트 frame은 화면을 채울 때 화면의 안전 영역(Safe area)을 준수합니다. 만일 안전영역 밖에까지 확장되도록 frame을 구성 하려면

.frame()..edgesIgnoringSafeArea(.all)

이렇게하여 안전 영역을 무시할 수 있습니다. (위의 조건 .all 뿐만 아니라 

의 옵션들도 있습니다.)

 

5. GeometryReader

GeometryReader로 뷰를 감싸고 컨테이너의 크기를 식별 할 수 있습니다.

 var body: some View {
        GeometryReader{ geometry in
            Text("JeongUPark").font(.largeTitle)
                .frame(width: geometry.size.width/2, height: geometry.size.height/2, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
        }
    }

이렇게 뷰를 감싸고 있는 컨테이너의 크기를 식별하고 그 크기를 사용하여 뷰의 넓이 높이를 정해줄 수 있습니다.

 

반응형