Home > AI > IOS > SwiftUI >

UIPageViewController

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

Leave a Reply