SwiftUI

SwiftUI - 스택, 프레임

iosos 2024. 1. 13. 15:54

스택

  • VStack(수직), HStack(수평), ZStack(중첩) 형태인 3개의 스택 레이아웃 뷰 제공
  • 스택은 View 파일 내에 하위 뷰들이 스택 뷰에 포함되도록 선언함
  • 3개의 이미지 뷰가 HStack에 포함되는 코드
import SwiftUI

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

 

 

 

 

  • VStack 사용
import SwiftUI

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

 

 

 

 

 

  • 다른 스택 안에 스택을 포함시켜 복잡한 레이아웃 설계 가능
struct Stack_20: View {
    var body: some View {
        VStack{
            Text("Financial Results")
                .font(.title)
            
            HStack{
                Text("Q1 Sales")
                    .font(.headline)
                
                VStack{
                    Text("January")
                    Text("February")
                    Text("March")
                }
                
                VStack{
                    Text("$1000")
                    Text("$200")
                    Text("$3000")
                    
                }
            }
        }
    }
}

 

 

 

 

 

 

Spacer, alignment, padding

  • Spacer : 뷰 사이의 공간을 추가하는 컴포넌트
  • 스택 안에서 사용하면 배치된 뷰들의 간격을 제공하기 위해 스택의 방향에 따라 유연하게 확장 축소
struct Stack_20: View {
    var body: some View {
        VStack{
            Text("Financial Results")
                .font(.title)
            
            HStack{
                Text("Q1 Sales")
                    .font(.headline)
                Spacer()
                VStack{
                    Text("January")
                    Text("February")
                    Text("March")
                }
		Spacer()
                VStack{
                    Text("$1000")
                    Text("$200")
                    Text("$3000")
                    
                }
            }
        }
    }
}

 

 

 

 

 

 

  • alignment : 정렬
  • 스택의 정렬은 스택이 선언될 때 정렬 값을 지정하면 됨
struct Stack_20: View {
    var body: some View {
        VStack(alignment: .center){
            Text("Financial Results")
                  .font(.title)
        }
    }
}

 

 

 

 

 

 

  • spacing : 간격
// 왼쪽 간격 15
struct Stack_20: View {
    var body: some View {
        VStack(alignment: .center, spacing: 15){
            Text("Financial Results")
                  .font(.title)
            Text("Financial Results")
                  .font(.title)
        }
    }
}

// 오른쪽 간격 100
struct Stack_20: View {
    var body: some View {
        VStack(alignment: .center, spacing: 100){
            Text("Financial Results")
                  .font(.title)
            Text("Financial Results")
                  .font(.title)
        }
    }
}

 

 

 

 

 

 

 

  • padding : 뷰 주변의 간격을 조절하는 수정자
  • 매개변수 없이 호출하면 레이아웃, 콘텐트, 화면 크기에 대한 최적의 간격을 자동으로 사용
// 매개변수 x
Text("Financial Results")
     .padding()

// 매개변수 o
Text("Financial Results")
     .padding(10)

// 특정 방향에만 적용
Text("Financial Results")
     .padding(.top, 10)

 

 

 

 

  • 세가지 방법 모두 적용
struct Stack_20: View {
    var body: some View {
        VStack(alignment: .center, spacing: 15){
            Text("Financial Results")
                .font(.title)
            
            HStack(alignment : .top){
                Text("Q1 Sales")
                    .font(.headline)
                Spacer()
                VStack(alignment : .leading){
                    Text("January")
                    Text("February")
                    Text("March")
                }
                Spacer()
                VStack(alignment : .leading){
                    Text("$1000")
                    Text("$200")
                    Text("$3000")
                    
                }
                .padding(5)
            }
            .padding(5)
        }
        .padding(5)
    }
}

 

 

 

 

 

 

 

 

 

컨테이너의 자식 뷰 제한

  • 컨테이너 뷰는 직접적인 하위 뷰를 10개로 제한함 → 10개 이상의 자식 뷰를 담으면 오류 발생
  • 10 개 이상의 뷰가 필요할 때 Group 뷰 사용
  • 12개의 Text 뷰가 Group 컨테이너로 나눠져 VStack에는 단 2개의 직접적인 자식 뷰만 포함됨
struct Stack_20: View {
    var body: some View {
        VStack(alignment: .center, spacing: 10){
            Group{
                Text("Sample Text")
                Text("Sample Text")
                Text("Sample Text")
                Text("Sample Text")
                Text("Sample Text")
                Text("Sample Text")
            }
            Group{
                Text("Sample Text")
                Text("Sample Text")
                Text("Sample Text")
                Text("Sample Text")
                Text("Sample Text")
                Text("Sample Text")
            }
        }
    }
}

  • Group은 여러 뷰에서 작업을 수행할 때 유용함
  • Group에 뷰들을 포함시키고 숨기는 명령을 주면 하나의 명령으로 모든 뷰를 숨길 수 있음

 

 

 

 

 

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

  • HStack은 텍스트 뷰를 한 줄로 보여줌
struct Stack_20: View {
    var body: some View {
        HStack{
            Image(systemName: "airplane")
            Text("Flight times : ")
            Text("London")
        }
        .font(.largeTitle)
    }
}

 

 

 

 

 

 

  • lineLimit() 수정자 : 텍스트를 몇 줄로 표현할지 정할 수 있음
struct Stack_20: View {
    var body: some View {
        HStack{
            Image(systemName: "airplane")
            Text("Flight times : ")
            Text("London")
        }
        .font(.system(size: 50))
        .lineLimit(1)
    }
}

 

 

 

 

 

 

  • 우선순위 가이드가 없으면 스택 뷰는 안에 포함된 뷰들의 길이와 여유공간을 기반으로 텍스트를 어떻게 자를지 결정함
  • layoutPriority() 수정자 : 우선순위 적용 수정자
    • 스택에 있는 뷰에 추가될 수 있음
    • 높은 숫자가 더 큰 우선순위를 갖게 되어 잘리는 현상이 사라짐
    • ex) ‘Flight times’ 텍스트보다 목적지 이름이 더 중요한 경우
struct Stack_20: View {
    var body: some View {
        HStack{
            Image(systemName: "airplane")
            Text("Flight times : ")
            Text("London").layoutPriority(1)
        }
        .font(.system(size: 50))
        .lineLimit(1)
    }
}

 

 

 

 

 

 

 

 

 

SwiftUI 프레임

  • 뷰는 자신의 콘텐트와 자신이 속한 레이아웃에 따라 자동으로 크기 조절이 됨
  • 뷰의 크기나 위치는 스택 레이아웃을 사용하여 조절할 수 있지만, 때로는 뷰 자체가 특정 크기나 영역에 맞아야 함
  • 이를 위해 frame 수정자 사용
  • 다음은 경계선이 있는 Text 뷰
struct Stack_20: View {
    var body: some View {
        Text("Hello World")
            .font(.largeTitle)
            .border(.black)
    }
}

→ frame 수정자가 없으면 텍스트 뷰는 콘텐트에 맞게 크기가 조절됨

 

 

 

  • 텍스트 뷰의 높이와 폭을 100으로 설정
struct Stack_20: View {
    var body: some View {
        Text("Hello World")
            .font(.largeTitle)
            .border(.black)
            .frame(width: 100, height: 100, alignment: .center)
    }
}

 

→ text가 길어지면 글자가 잘리는 현상 발생 → frame 내 최대 영역과 최소 영역을 지정하여 해결

 

 

 

 

 

 

struct Stack_20: View {
    var body: some View {
        Text("Hello World!!!")
            .font(.largeTitle)
            .border(.black)
            .frame(minWidth: 100, maxWidth: 300, minHeight: 100, maxHeight: 100, alignment: .center)

	// 최솟값과 최댓값을 각각 0과 무한대로 설정하여 사용 가능한 모든 영역 차지하도록 구성
	// .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
    }
}

 

 

 

 

 

 

 

 

  • 안전 영역 : 아이폰 x 이상 모델의 카메라 노치, 와이파이, 셀루러 데이터 등 아이콘을 표시하는 화면 상단
  • 안전 영역까지 frame을 확장하려면 edgesIgnoringSafeArea() 수정자 사용
.edgesIgnoringSafeArea(.all)

 

 

 

 

frame과 GeometryReader

  • 프레임은 뷰들을 담고 있는 컨테이너의 크기에 따라 조절되도록 구현 가능
  • GeometryReader로 뷰를 감싸고 컨테이너의 크기를 식별하기 위한 리더를 이용하여 가능
  • 리더는 프레임 크기를 계산할 때 사용
  • 두 개의 텍스트 뷰를 포함하는 VStack의 크기를 기준으로 텍스트 뷰의 크기를 설정
struct Stack_20 : View {
    var body: some View {
        GeometryReader { geometry in
            VStack{
                Text("Hello World, how are you?")
                    .font(.largeTitle)
                    .frame(width: geometry.size.width / 2,
                           height: (geometry.size.height / 4) * 3)
                Text("Goodbye World")
                    .font(.largeTitle)
                    .frame(width: geometry.size.width / 3,
                           height: geometry.size.height / 4)
            }
        }
    }
}