๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐ŸŽ iOS

[SwiftUI] Stack (VStack/HStack/ZStack)

by hyebin (Helia) 2024. 4. 8.
๋ฐ˜์‘ํ˜•

Stack

๋ทฐ๋ฅผ ์ˆ˜์ง ๋˜๋Š” ์ˆ˜ํ‰์œผ๋กœ ์ •๋ ฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ์ปจํ…Œ์ด๋„ˆ์ž…๋‹ˆ๋‹ค.

Stack์„ ์‚ฌ์šฉํ•ด์„œ ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋ทฐ๋ฅผ ๊ทธ๋ฃนํ™”ํ•˜๊ณ  ๋ ˆ์ด์•„์›ƒ์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

VSatck

๋ทฐ๋ฅผ ์ˆ˜์ง์œผ๋กœ ์Œ“๋Š” ์Šคํƒ์ž…๋‹ˆ๋‹ค. ์„ ์–ธ๋œ ์ˆœ์„œ๋Œ€๋กœ ๋ทฐ๋“ค์€  ์œ„์—์„œ ์•„๋ž˜๋กœ ์Œ“์ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Text("First View")
            Text("Second View")
            Text("Third View")
        }
    }
}

Alignment

VStack์—์„œ alignment ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด ํ•˜์œ„ ๋ทฐ์˜ ์ •๋ ฌ ๋ฐฉ๋ฒ•์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

.leading์„ ์„ ํƒํ•˜๋ฉด ์™ผ์ชฝ์„ ๊ธฐ์ค€์œผ๋กœ,  .trailing์„ ์„ ํƒํ•˜๋ฉด ์˜ค๋ฅธ์ชฝ์„ ๊ธฐ์ค€์œผ๋กœ, .center๋ฅผ ์„ ํƒํ•˜๋ฉด ์ค‘์•™์„ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ๋ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ๊ฐ’์€ center์ž…๋‹ˆ๋‹ค. 

<- trailing           leading ->

LazyVStack

์ง€์—ฐ ๋กœ๋”ฉ(lazy loading) ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜๋Š” VStack์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ VStack๊ณผ ๋น„์Šทํ•˜์ง€๋งŒ, ํ™”๋ฉด์— ํ‘œ์‹œํ•  ๋•Œ ํ•„์š”ํ•œ ๋ทฐ๋งŒ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค. ๋งŽ์€ ์ˆ˜์˜ ํ•ญ๋ชฉ์„ ํ‘œ์‹œํ•˜๋Š” ๊ฒฝ์šฐ์— ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ์ค„์—ฌ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import SwiftUI

struct ContentView: View {
    var body: some View {
        ScrollView {
            LazyVStack {
                ForEach(1..<100) { number in
                    Text("Row \(number)")
                }
            }
        }
    }
}

 

HStack

๋ทฐ๋ฅผ ์ˆ˜ํ‰์œผ๋กœ ์Œ“๋Š” ์Šคํƒ์ž…๋‹ˆ๋‹ค. ์„ ์–ธ๋œ ์ˆœ์„œ๋Œ€๋กœ ๋ทฐ๋“ค์€ ์™ผ์ชฝ์—์„œ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์Œ“์ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

import SwiftUI

struct ContentView: View {
    var body: some View {
        HStack {
            Text("First View")
            Text("Second View")
            Text("Third View")
        }
    }
}

Alignment

HStack์—์„œ alignment ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด ํ•˜์œ„ ๋ทฐ์˜ ์ •๋ ฌ ๋ฐฉ๋ฒ•์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

.top์„ ์„ ํƒํ•˜๋ฉด ์œ„์ชฝ์„ ๊ธฐ์ค€์œผ๋กœ,  .trailing์„ ์„ ํƒํ•˜๋ฉด ์•„๋ž˜์ชฝ์„ ๊ธฐ์ค€์œผ๋กœ, .center๋ฅผ ์„ ํƒํ•˜๋ฉด ์ค‘์•™์„ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ๋ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ๊ฐ’์€ center ์ž…๋‹ˆ๋‹ค. 

 

์ฐจ์ด๋ฅผ ๋น„๊ตํ•˜๊ธฐ ์œ„ํ•ด ๋‘ ๋ฒˆ์งธ text์— ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•ด ์ฃผ๊ณ , HStack ๋ทฐ์— ๋ฐฐ๊ฒฝ ์ƒ‰์„ ํšŒ์ƒ‰์œผ๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

import SwiftUI

struct ContentView: View {
    var body: some View {
        HStack(alignment: .top) {
            Text("First View")
            Text("Second View")
                .frame(width: 100, height: 300)
            Text("Third View")
        }
        .background(Color.gray)
    }
}

<- top               bottom ->

LazyHStack

์ง€์—ฐ ๋กœ๋”ฉ(lazy loading) ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜๋Š” HStack์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ HStack๊ณผ ๋น„์Šทํ•˜์ง€๋งŒ, ํ™”๋ฉด์— ํ‘œ์‹œํ•  ๋•Œ ํ•„์š”ํ•œ ๋ทฐ๋งŒ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค. ๋งŽ์€ ์ˆ˜์˜ ํ•ญ๋ชฉ์„ ํ‘œ์‹œํ•˜๋Š” ๊ฒฝ์šฐ์— ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ์ค„์—ฌ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import SwiftUI

struct ContentView: View {
    var body: some View {
        ScrollView(.horizontal) {
            LazyHStack {
                ForEach(1..<100) { number in
                    Text("Item \(number)")
                }
            }
        }
    }
}

ZStack

๋ทฐ๋ฅผ ๊ฒน์ณ์„œ ์Œ“๋Š” ์Šคํƒ์ž…๋‹ˆ๋‹ค. ์„ ์–ธ๋œ ์ˆœ์„œ๋Œ€๋กœ ๋ทฐ๋“ค์€ ๊ฒน์ณ์„œ ์Œ“์ž…๋‹ˆ๋‹ค. ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰์— ์„ ์–ธ๋œ ๋ทฐ๊ฐ€ ๊ฐ€์žฅ ์œ„์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ZStack์€ ๋ทฐ๋ฅผ 3D ๊ณต๊ฐ„์—์„œ ๊ฒน์น˜๊ฒŒ ํ•˜์—ฌ ๋‹ค์–‘ํ•œ ์‹œ๊ฐ์  ํšจ๊ณผ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

import SwiftUI

struct ContentView: View {
    var body: some View {
        ZStack {
            Rectangle()
                .fill(Color.blue)
                .frame(width: 200, height: 200)
            
            Circle()
                .fill(Color.red)
                .frame(width: 150, height: 150)
        }
    }
}

ZIndex

ZStack์— ์†ํ•œ ๋ทฐ์˜ ์ˆœ์„œ๋ฅผ ์„ค์ •ํ•˜๋Š” ์ˆ˜์ •์ž์ž…๋‹ˆ๋‹ค. zIndex๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ทฐ์˜ ์ •๋ ฌ ์ˆœ์„œ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ˆซ์ž๊ฐ€ ์ž‘์„์ˆ˜๋ก ๋’ค์—, ํด์ˆ˜๋ก ์•ž์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

import SwiftUI

struct ContentView: View {
    var body: some View {
        ZStack {
            Rectangle()
                .fill(Color.blue)
                .frame(width: 200, height: 200)
                .zIndex(1)
            
            Circle()
                .fill(Color.red)
                .frame(width: 150, height: 150)
                .zIndex(0)
        }
    }
}

์„ ์–ธ์ˆœ์„œ๋Œ€๋กœ๋ผ๋ฉด ์œ„์˜ ์‚ฌ์ง„์ฒ˜๋Ÿผ ์‚ฌ๊ฐํ˜• ์œ„์— ์›์ด ํ‘œ์‹œ๋˜์–ด์•ผ ํ•˜์ง€๋งŒ, zIndex๋กœ ์ˆœ์„œ๋ฅผ ๋ฐ”๊พธ์–ด ์‚ฌ๊ฐํ˜•์ด ๋” ์œ„์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์›์ด ๋ณด์ด์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์›์˜ ํฌ๊ธฐ๋ฅผ (width: 300, height: 300)์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด ์› ์œ„์— ์‚ฌ๊ฐํ˜•์ด ํ‘œ์‹œ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<- (width :  150 ,  height :  150 )                 (width :  300 ,  height :  300 ) ->

 

๋ฐ˜์‘ํ˜•

'๐ŸŽ iOS' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[RxSwift] RxSwift๋ž€?  (0) 2024.06.03
[SwiftUI] Text  (0) 2024.04.18
[SwiftUI] Property Wrappers  (0) 2024.04.04
[๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ] ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ž€?  (0) 2023.09.18
[SwiftUI] SwiftUI๋ž€?  (0) 2023.03.15