๋์ผํ UI ๊ตฌ์ฑ์ ๊ฐ์ง์ง๋ง ๊ฐ๋ก๋ชจ๋์์ ์ธ๋ก๋ชจ๋๋ก ๋ณ๊ฒฝ๋ ๋ ํ๋ฉด์ ๋์ด๊ฐ ๋ฌ๋ผ์ง๊ฒ ๋ฉ๋๋ค. ํน์ UI์์๋ ํ๋ฉด์ด ๊นจ์ง ์ ์์ด์ ์ด์ ๋์ํด์ผ ํด์. ViewBuilder๋ฅผ ์ฌ์ฉํ๋ฉด ์ฌ๋ฌ ํ๋ฉด์์ ๋์ ๊ฐ๋ฅํ View๋ฅผ ์์ฑํ ์ ์์ต๋๋ค!
ํน์ ViewBuilder๊ฐ ๋ฌด์์ธ์ง ์ ๋ชจ๋ฅด๊ฒ ๋ค๋ฉด ์๋ ํฌ์คํ ์ ์ฐธ๊ณ ํ์ธ์!
ํน์ ์นด์นด์คํก ์ ๊ธํ๋ฉด์ ๋ณด์ ์ ์์ผ์ ๊ฐ์?
์ ๊ธ ํ๋ฉด์์ ์ธ๋ก ๋ชจ๋๋ก ๋ณ๊ฒฝํ๋ฉด ์ด์ ๋์ํด์ UI๊ฐ ์ฌ๋ฐฐ์น ๋์. ๊ทธ๋ฌ๋ SwiftUI๋ก ๋จ์ํ View๋ฅผ ๊ทธ๋ฆฌ๊ฒ ๋๋ฉด ์๋์ ๊ฐ์ด ๋ฉ๋๋ค
์ธ๋ก ๋ชจ๋์์๋ ์ ๋์ค๋ ๋ทฐ๊ฐ ๊ฐ๋ก ๋ชจ๋์์๋ ์ ์๋ ๊ณต๊ฐ์ด ๋ถ์กฑํด์ ์งค๋ฆฌ๊ฒ ๋๊ณ , ๋์ด๊ฐ ์ปค์ ธ์ UI๊ฐ ์์ผ๋ก ๋์ด๋๊ฒ ๋ฉ๋๋ค.
์ด๋ฅผ ๋์ํ๊ธฐ ์ํด GeometryReader์ @ViewBuilder๋ฅผ ์ฌ์ฉํด ์ค ๊ฒ์!
์์ฑ๋ ์ฝ๋๋ ์๋ ๋ ํฌ์งํ ๋ฆฌ์์ ๋ค์ด๋ก๋ ๋ฐ์ผ์๋ฉด ๋ฉ๋๋ค.
๊ธฐ๋ณธ View ๊ทธ๋ฆฌ๊ธฐ
ํฌ๊ฒ ๋ ๋ถ๋ถ์ผ๋ก ์ชผ๊ฐ์ด View๋ฅผ ๊ทธ๋ ค ์ค๋๋ค. ์ํธ ์ ๋ ฅ๊ณผ ์ค๋ช ๊ธ, ๋ฒํผ์ ๋๋ ์ ๋ ์ฑ์์ง๋ ์์ ์ธ๋ก ๋ชจ๋์์ ์ผ์ชฝ์ ์์นํ๊ฒ ๋๊ณ ๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ ฅํ๋ ํคํจ๋๋ ์ค๋ฅธ์ชฝ์ผ๋ก ์์นํ๊ฒ ๋ฉ๋๋ค. ๊ทธ๋์ ํคํจ๋๋ฅผ ํ๋์ View๋ก ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ฅผ ๋ค๋ฅธ View๋ก ์ชผ๊ฐ์ด ์ฝ๋ฉํด ์ค๊ฒ์
struct InfoView: View {
var body: some View {
VStack(spacing: 0) {
Text("์ํธ ์
๋ ฅ")
.font(.title)
.fontWeight(.bold)
.padding(.bottom, 10)
Text("์นด์นด์คํก ์ํธ๋ฅผ ์
๋ ฅํด ์ฃผ์ธ์.")
.foregroundStyle(.gray)
.font(.system(size: 14))
.padding(.bottom, 18)
HStack(spacing: 20) {
ForEach(0..<4) { index in
Image(systemName: "circle")
}
}
}
}
}
๋น์ฆ๋์ค ๋ก์ง์ ์ ์ธํ๊ณ UI์ ๊ด๋ จ๋ ์ฝ๋๋ง ๊ฐ๋จํ ์์ฑํ์ด์. ์ด์ ํคํจ๋ ์ฝ๋๋ฅผ ์์ฑํ ๊ฒ์
struct KeypadView: View {
let numbers = [
["1", "2", "3"],
["4", "5", "6"],
["7", "8", "9"],
[" ", "0", " "]
]
var body: some View {
VStack(spacing: 0) {
ForEach(0..<numbers.count, id: \.self) { rowIndex in
HStack(spacing: 0) {
ForEach(0..<numbers[rowIndex].count, id: \.self) { columnIndex in
Button {
print(numbers[rowIndex][columnIndex])
} label: {
if rowIndex == numbers.count - 1 && columnIndex == numbers[rowIndex].count - 1 {
Image(systemName: "eraser")
.keypadButtonStyle()
} else {
Text("\(numbers[rowIndex][columnIndex])")
.keypadButtonStyle()
}
} //: Button
}
}
} //: ForEach
} //: VStack
}
}
struct KeypadButtonStyle: ViewModifier {
func body(content: Content) -> some View {
content
.font(.title)
.foregroundStyle(.black)
.padding(.vertical, 20)
.frame(maxWidth: .infinity)
}
}
extension View {
func keypadButtonStyle() -> some View {
self.modifier(KeypadButtonStyle())
}
}
์ค๋ณต๋๋ modifier๋ custom ViewModifier๋ฅผ ๋ง๋ค์ด ์ฃผ์์ด์.
@ViewBuilder์ GeometryReader ์ฌ์ฉํ๊ธฐ
@ViewBuilder๋ฅผ ์ฌ์ฉํ๋ฉด ํด๋ก์ ๋ก ๋จ์ผ ๋ทฐ๋ค์ ๋ฐ์ ์ ์๊ณ ์ด ๋จ์ผ ๋ทฐ๋ฅผ ์กฐํฉํด์ ๋ณตํฉ ๋ทฐ๋ฅผ ๋ง๋ค๊ฒ ๋์. VStack๊ณผ ScrollView์ ๊ฐ์ ์ปจํ ์ด๋ ์ญํ์ ํ๋ Custom View๋ฅผ ์์ฑํ ์ ์์ด์.
struct LandscapeManageView<Content: View>: View {
let content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
var body: some View {
GeometryReader { geometry in
if geometry.size.height > geometry.size.width {
VStack {
content
} //: VStack
} else {
HStack(alignment: .center) {
content
} //: HStack
.frame(maxHeight: .infinity)
}
} //: GeometryReader
}
}
์ฒ์์๋ @Environment(.\horizontalSizeClass)๋ฅผ ์ด์ฉํ๋ฉด ๋๋ ์ค ์์๋๋ฐ iPad ๋์์ ์ํด ์ค๋น๋ ๊ฐ์ด๋๋ผ๊ตฌ์! GeometryReader๋ฅผ ์ฌ์ฉํด์ ๊ฐ๋จํ๊ฒ ๋์ด๊ฐ ๋์ด๋ณด๋ค ๋ ํฐ ๊ฒฝ์ฐ ์ธ๋ก๋ชจ๋๋ก, ์๋๋ผ๋ฉด ๊ฐ๋ก ๋ชจ๋๋ก ์ง์ ํด ์ฃผ๋ฉด ๋ฉ๋๋ค. ํด๋ก์ ๋ก ์ ๋ฌ๋ฐ์ View๋ content๋ผ๋ ๊ฐ์ผ๋ก ๋ฐ์์ body์ ํฌํจ ์์ผ์ค์.
HStack ์ ๊ฒฝ์ฐ ์ปจํ ์ธ ์ ํฌ๊ธฐ์ ๋ง๊ฒ ๊ฐ์ธ์ง๊ธฐ ๋๋ฌธ์ maxHeight๋ฅผ infinity๋ก ์ค ๋ค alignment๋ฅผ center๋ก ์ง์ ํด ์ฃผ๋ฉด ๋ฉ๋๋ค.
์ค์ ์ฌ์ฉํ๊ธฐ
struct ContentView: View {
var body: some View {
LandscapeManageView {
Spacer()
InfoView()
Spacer()
KeypadView()
}
}
}
๊ฐ๋ก๋ชจ๋์ ์ธ๋ก๋ชจ๋๋ฅผ ์ง์ํ๊ณ ์ถ์ ํ๋ฉด์์ ์์ฑํ LandscapeManageView๋ฅผ ์ ์ฉํด ์ฃผ๋ฉด ๋ฉ๋๋ค. ๊ฐ๊ฐ์ ํ๋ฉด์์ GeometryReader๋ฅผ ์ฌ์ฉํด ํ๋ณํ๋ ์กฐ๊ฑด์๊ณผ ๊ฐ ์กฐ๊ฑด์ ํด๋นํ๋ ๋ฆฌํด์ ์์ฑํ ํ์๊ฐ ์๊ธฐ ๋๋ฌธ์ ์ ์ฐํ๊ณ ์ฌ์ฌ์ฉ์ฑ์ด ๋๊ฒ ์ฝ๋๋ฅผ ์์ฑํด์ ๋์ํ ์ ์์ด์
์์ฑ ํ๋ฉด
์ฐธ๊ณ ์ฌ์ดํธ
์นด์นด์คํก ์ ๊ธํ๋ฉด
ViewBuilder์ ๋ํ ์ค๋ช https://www.avanderlee.com/swiftui/viewbuilder/
'iOS ๐ > SwiftUI' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[SwiftUI] VStack ๊ณผ LazyVStack ๋ญ๊ฐ ๋ค๋ฅธ ๊ฑธ๊น? (1) | 2023.10.08 |
---|---|
[SwiftUI] NavigationView (1) | 2023.09.22 |
[SwiftUI] ViewBuilder ์์๋ณด๊ธฐ (0) | 2023.09.19 |
[SwiftUI] Custom Font ์ง์ ํ๊ธฐ (with Figma) (2) | 2023.09.18 |
[SwiftUI] Link Text ๋ง๋ค๊ธฐ (๋ชจ๋ ๊ฑธ ์ค๋นํด ๋จ๋ค ๊ฐ์ ธ๋ค ์จ๋ผ!) (0) | 2023.08.27 |