SwiftUI에서 PageView 만들기

SteadySlower·2023년 3월 24일
0

SwiftUI

목록 보기
42/64

오늘 포스팅의 주제는 SwiftUI에서 UIPageView와 같은 뷰를 만드는 것입니다.

TabView

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)
    }
}

indexView

UIPageControl이라는 별도의 component를 사용해야 했던 UIKit과는 다르게 TabView에는 indexView를 자동으로 만들어 줍니다. indexDisplayMode의 설정을 통해서 해당 IndexDisplay를 항상 보이거나 항상 숨길수도 있습니다.

.tabViewStyle(.page(indexDisplayMode: .always))
.tabViewStyle(.page(indexDisplayMode: .never))

indexView 색 바꾸기

indexView색을 바꾸기 위해서는 UIKit의 코드를 빌려와야 합니다. 아래와 같이 UIPageControl의 appearance에서 currentPageIndicatorTintColor와 pageIndicatorTintColor의 색을 변경할 수 있습니다.

주의할 점은 이 코드는 이 앱에 나오는 모든 UIPageControl의 색을 바꾸는 코드입니다. 다른 화면에서는 다른 색이 필요하다면 해당 코드를 다시 실행시켜 설정을 덮어 씌워야 합니다.

private func setIndicator() {
    UIPageControl.appearance().currentPageIndicatorTintColor = UIColor(Color.yellow)
    UIPageControl.appearance().pageIndicatorTintColor = UIColor(Color.green)
}

indexView와 contents가 겹치지 않도록 하기!

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

indexViewStyle이라는 속성을 통해서 indexView의 회색 background가 보일지 말지 결정할 수 있습니다. 총 3가지 옵션으로 .always는 항상 보이기, .interactive는 indexView를 통해 페이지를 이동하는 경우에만, .never는 보이지 않기입니다.


Tag

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)
    }
}

profile
백과사전 보다 항해일지(혹은 표류일지)를 지향합니다.

0개의 댓글