TableView는 UITabBarController와 동일한 역할을 한다고 보시면 됩니다. 각각의 View를 TabBar에 등록하고 등록된 View 간의 전환을 담당합니다.
UITabBarController가 각각의 VC를 가지고 있듯이 TabView도 마찬가지로 각각의 View를 가지고 있습니다. 마찬가지로 각각의 VC들에 tabBarItem을 정의하듯이 View에 tabItem을 정의합니다.
import SwiftUI
struct ContentView: View {
var body: some View {
TabView {
Page(pageNumber: 1)
.tabItem({
Image(systemName: "1.circle")
Text("First Page")
})
Page(pageNumber: 2)
.tabItem({
Image(systemName: "2.circle")
Text("Second Page")
})
Page(pageNumber: 3)
.tabItem({
Image(systemName: "3.circle")
Text("Third Page")
})
}
}
}
struct Page: View {
let pageNumber: Int
var body: some View {
Text("\(pageNumber)번째 페이지입니다.")
}
}
먼저 선택된 Item의 색을 바꾸는 방법은 .accentColor를 사용하는 것입니다. (다만 이 메소드는 deprecated될 예정이라고 합니다ㅠ)
SwiftUI가 제공하는 탭바의 배경색과 선택되지 않는 아이템의 색을 바꾸는 API는 아직 없습니다. 여기서는 UIKit의 힘을 빌려야합니다. UIAppearance를 활용합니다.
import SwiftUI
struct ContentView: View {
var body: some View {
TabView {
Page(pageNumber: 1)
.tabItem({
Image(systemName: "1.circle")
Text("First Page")
})
Page(pageNumber: 2)
.tabItem({
Image(systemName: "2.circle")
Text("Second Page")
})
Page(pageNumber: 3)
.tabItem({
Image(systemName: "3.circle")
Text("Third Page")
})
}
.accentColor(.red)
.onAppear() {
UITabBar.appearance().backgroundColor = .black
UITabBar.appearance().unselectedItemTintColor = .green
}
}
}
기본적으로 탭 사이의 전환은 사용자의 탭바에 대한 터치 이벤트를 통해 이루어집니다. 하지만 프로그래밍적으로 코드를 통해 탭 사이의 전환을 만들 수도 있습니다.
TabView는 선언할 때 selection이라는 Binding 변수를 받을 수 있습니다. 부모뷰에서 @State로 선언된 selection 변수를 TabView에 전달합시다. @State로 선언되었기 때문에 selection 변수가 바뀌면 View가 re-render될 것입니다.
그리고 TabView의 하위 View에 .tag()메소드로 각각 인덱스를 붙여주어야 합니다. selection이 변하면 해당 인덱스를 가진 View가 나타날 것입니다.
import SwiftUI
struct ContentView: View {
@State private var selection: Int = 0
var body: some View {
TabView(selection: $selection) {
Page(pageNumber: 1, selection: $selection)
.tabItem({
Image(systemName: "1.circle")
Text("First Page")
})
.tag(0)
Page(pageNumber: 2, selection: $selection)
.tabItem({
Image(systemName: "2.circle")
Text("Second Page")
})
.tag(1)
Page(pageNumber: 3, selection: $selection)
.tabItem({
Image(systemName: "3.circle")
Text("Third Page")
})
.tag(2)
}
}
}
TabView에 속한 하위 View에도 Binding 변수인 selection을 전달하도록 합시다. 그리고 각각의 View에 버튼을 2개 추가합니다. 각각의 버튼의 역할은 selection의 값을 1 줄이거나 1 늘리는 역할을 합니다. 우리의 의도대로라면 해당 버튼을 누를 때마다 Binding 변수인 selection의 값이 변화하면서 TabView가 보여주는 View가 바뀌게 될 것입니다.
struct Page: View {
let pageNumber: Int
@Binding var selection: Int
var body: some View {
VStack {
Text("\(pageNumber)번째 페이지입니다.")
HStack {
Button(action: {
selection = selection - 1 >= 0 ? selection - 1 : 2
}, label: {
Text("이전 페이지")
})
Button(action: {
selection = (selection + 1) % 3
}, label: {
Text("다음 페이지")
})
}
}
}
}
UITabBarController와 UINavigationController를 함께 사용하는 것처럼 TabView와 NavigationView를 함께 사용할 수도 있습니다. TabView를 NavigationView로 감싸보겠습니다.
import SwiftUI
struct ContentView: View {
@State private var selection: Int = 0
var body: some View {
NavigationView {
TabView(selection: $selection) {
Page(pageNumber: 1, selection: $selection)
.tabItem({
Image(systemName: "1.circle")
Text("First Page")
})
.tag(0)
Page(pageNumber: 2, selection: $selection)
.tabItem({
Image(systemName: "2.circle")
Text("Second Page")
})
.tag(1)
Page(pageNumber: 3, selection: $selection)
.tabItem({
Image(systemName: "3.circle")
Text("Third Page")
})
.tag(2)
}
.navigationTitle("Page \(selection + 1)")
}
}
}
그리고 하위 View인 Page에 상세 페이지로 가는 Navigation Link를 넣어서 간략한 상세페이지를 구현해보았습니다.
struct Page: View {
let pageNumber: Int
@Binding var selection: Int
var body: some View {
VStack {
Text("\(pageNumber)번째 페이지입니다.")
HStack {
Button(action: {
selection = selection - 1 >= 0 ? selection - 1 : 2
}, label: {
Text("이전 페이지")
})
Button(action: {
selection = (selection + 1) % 3
}, label: {
Text("다음 페이지")
})
}
NavigationLink("상세 페이지", destination: {
Text("Page \(selection + 1)의 상세페이지입니다.")
})
}
}
}