오늘 포스팅의 주제는 SwiftUI에서 UIPageView와 같은 뷰를 만드는 것입니다.
UIPageView와 같은 뷰를 만들기 위해서 사용되는 뷰는 TabView입니다. 보통 이 뷰는 주로 하단에 존재하는 탭바를 만들기 위해서 많이 사용되는데요. tabViewStyle의 tabViewStyle을 .page로 지정해주면 됩니다.
struct InterimView: View {
@State var email: String = ""
var body: some View {
TabView {
Color.red
Color.blue
Color.green
}
.tabViewStyle(.page)
}
}
UIPageControl이라는 별도의 component를 사용해야 했던 UIKit과는 다르게 TabView에는 indexView를 자동으로 만들어 줍니다. indexDisplayMode의 설정을 통해서 해당 IndexDisplay를 항상 보이거나 항상 숨길수도 있습니다.
.tabViewStyle(.page(indexDisplayMode: .always))
.tabViewStyle(.page(indexDisplayMode: .never))
indexView색을 바꾸기 위해서는 UIKit의 코드를 빌려와야 합니다. 아래와 같이 UIPageControl의 appearance에서 currentPageIndicatorTintColor와 pageIndicatorTintColor의 색을 변경할 수 있습니다.
주의할 점은 이 코드는 이 앱에 나오는 모든 UIPageControl의 색을 바꾸는 코드입니다. 다른 화면에서는 다른 색이 필요하다면 해당 코드를 다시 실행시켜 설정을 덮어 씌워야 합니다.
private func setIndicator() {
UIPageControl.appearance().currentPageIndicatorTintColor = UIColor(Color.yellow)
UIPageControl.appearance().pageIndicatorTintColor = UIColor(Color.green)
}
TabView 안에서 VStack을 사용할 때 주의할 점입니다. 위에 Color가 indexView를 덮은 것에서도 볼 수 있듯이 indexView는 단독으로 공간을 차지 하는 것이 아닌 TabView의 content 앞에 존재하는 것입니다. (ZStack이라고 생각하면 쉽습니다.)
따라서 아래처럼 contents가 indexView 아래에 위치하거나 심지어는 두 뷰가 겹쳐서 보일 수도 있습니다. 그것을 원하지 않는다면 padding을 사용하면 됩니다.
struct InterimView: View {
var body: some View {
TabView {
VStack {
Color.red
Spacer()
Text("안녕하세요")
.padding(.bottom, 40) //👉 패딩 주기
}
Color.blue
Color.green
}
.onAppear { setIndicator() }
.tabViewStyle(.page(indexDisplayMode: .always))
}
private func setIndicator() {
UIPageControl.appearance().currentPageIndicatorTintColor = UIColor(Color.yellow)
UIPageControl.appearance().pageIndicatorTintColor = UIColor(Color.green)
}
}
indexViewStyle이라는 속성을 통해서 indexView의 회색 background가 보일지 말지 결정할 수 있습니다. 총 3가지 옵션으로 .always는 항상 보이기, .interactive는 indexView를 통해 페이지를 이동하는 경우에만, .never는 보이지 않기입니다.
PageView를 사용하다가 보면 현재 선택된 페이지가 몇 번째 페이지인지 알 필요가 있을 때가 있습니다. View안에 @State 변수를 하나 선언하고 그 변수를 TabView와 Binding 해 놓음으로서 알 수 있습니다.
또한 각각의 TabView의 하위 View에 해당 View가 선택되었을 때 변수를 어떤 값으로 변경할 것인가를 tag를 통해서 지정해주어야 합니다.
TabView는 page가 변경되면 해당 변수를 tag에 지정된 값으로 변경해서 페이지가 변경되었음을 알립니다.
import SwiftUI
struct InterimView: View {
@State private var pageNumber = 0
var body: some View {
VStack {
Text("\(pageNumber + 1)번째 페이지")
TabView(selection: $pageNumber) {
Color.red
.tag(0)
Color.blue
.tag(1)
Color.green
.tag(2)
}
.onAppear { setIndicator() }
.tabViewStyle(.page(indexDisplayMode: .always))
.indexViewStyle(.page(backgroundDisplayMode: .never))
}
}
private func setIndicator() {
UIPageControl.appearance().currentPageIndicatorTintColor = UIColor(Color.yellow)
UIPageControl.appearance().pageIndicatorTintColor = UIColor(Color.green)
}
}