Example 1: wrap the UIPageViewController to SwiftUI
import SwiftUI
struct ContentView: View {
@State var currentPage: Int = 0
var body: some View {
MyPageViewController(pages: [
MyImageView(systemName: "pencil"),
MyImageView(systemName: "pencil.circle"),
MyImageView(systemName: "pencil.slash")],
currentPage: $currentPage)
Text("currentPage \(currentPage)")
}
}
struct MyImageView: View {
var systemName: String
var body: some View {
Image(systemName: systemName)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 200, height: 200)
}
}
struct MyPageViewController<Page: View>: UIViewControllerRepresentable {
var pages: [Page]
typealias UIViewControllerType = UIPageViewController
@Binding var currentPage: Int
func makeCoordinator() -> Coordinator {
Coordinator(pageVC: self)
}
func makeUIViewController(context: Context) -> UIPageViewController {
let vc = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
vc.dataSource = context.coordinator
vc.delegate = context.coordinator
return vc
}
func updateUIViewController(_ uiViewController: UIPageViewController, context: Context) {
uiViewController.setViewControllers([context.coordinator.controllers[currentPage]],
direction: .forward,
animated: true,
completion: nil)
}
class Coordinator: NSObject, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
var parent: MyPageViewController
var controllers = [UIViewController]()
init(pageVC: MyPageViewController) {
self.parent = pageVC
self.controllers = parent.pages.map { UIHostingController(rootView: $0)}
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let idx = controllers.firstIndex(of: viewController) else {
return nil
}
if idx == 0 {
return controllers.last
}
return controllers[idx - 1]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let idx = controllers.firstIndex(of: viewController) else {
return nil
}
if idx == controllers.count-1 {
return controllers.first
}
return controllers[idx + 1]
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed,
let currentVC = pageViewController.viewControllers?.first,
let idx = controllers.firstIndex(of: currentVC) {
parent.currentPage = idx
}
}
}
}