PageView (UIPageViewController) 的条件同级中断分页

Posted

技术标签:

【中文标题】PageView (UIPageViewController) 的条件同级中断分页【英文标题】:Conditional sibling of a PageView (UIPageViewController) breaks paging 【发布时间】:2019-12-22 22:20:06 【问题描述】:

我在 SwiftUI 中使用this UIPageViewController implementation 作为起点,但是当currentPage 是最后一页时,我希望有一个视图(例如:“OK”文本或按钮)出现在 PageView 的上方或下方。

但是,每当我在 PageView 上方或下方添加 if 语句时,只要我滑动到第二页,所有其他页面就会被删除,并且无法在页面之间滑动。如果我取出if 逻辑,一切正常。代码如下:

PageViewController:

struct PageViewController: UIViewControllerRepresentable 
    var controllers: [UIViewController]

    @Binding var currentPage: Int

    func makeCoordinator() -> Coordinator 
        Coordinator(self)
    

    func makeUIViewController(context: Context) -> UIPageViewController 
        let pageViewController = UIPageViewController(
            transitionStyle: .scroll,
            navigationOrientation: .horizontal)
        pageViewController.dataSource = context.coordinator
        pageViewController.delegate = context.coordinator

        return pageViewController
    

    func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) 
        var dir = UIPageViewController.NavigationDirection.forward
        if let visibleViewController = pageViewController.viewControllers?.first,
            let nextPage = controllers.firstIndex(of: visibleViewController) 
            if currentPage < nextPage 
                dir = .reverse
            
        

        pageViewController.setViewControllers([controllers[currentPage]], direction: dir, animated: true)
    

    class Coordinator: NSObject, UIPageViewControllerDataSource, UIPageViewControllerDelegate 
        var parent: PageViewController

        init(_ pageViewController: PageViewController) 
            self.parent = pageViewController
        

        func pageViewController(
            _ pageViewController: UIPageViewController,
            viewControllerBefore viewController: UIViewController) -> UIViewController?
        
            guard let index = parent.controllers.firstIndex(of: viewController) else 
                return nil
            
            if index == 0 
                return nil
            
            return parent.controllers[index - 1]
        

        func pageViewController(
            _ pageViewController: UIPageViewController,
            viewControllerAfter viewController: UIViewController) -> UIViewController?
        
            guard let index = parent.controllers.firstIndex(of: viewController) else 
                return nil
            
            if index + 1 == parent.controllers.count 
                return nil
            
            return parent.controllers[index + 1]
        

        func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) 
            if completed,
                let visibleViewController = pageViewController.viewControllers?.first,
                let index = parent.controllers.firstIndex(of: visibleViewController)
            
                parent.currentPage = index
            
        
    

页面视图:

struct PageView<Page: View>: View 
    var viewControllers: [UIHostingController<Page>]
    @Binding var currentPage: Int

    init(_ views: [Page], currentPage: Binding<Int>) 
        self._currentPage = currentPage
        self.viewControllers = views.map  UIHostingController(rootView: $0) 
    

    var body: some View 
        PageViewController(controllers: viewControllers, currentPage: $currentPage).frame(width: UIScreen.main.bounds.width)
    

主内容视图:

struct TestView: View 
    @State private var curPage: Int = 0

    var body: some View 
        ZStack 
            Color(.secondarySystemBackground)

            VStack 
                if curPage == 9892832 
                    Text("OK").padding().foregroundColor(.blue).padding(.top, 60)
                

                PageView([
                    Text("Page 1"),
                    Text("Page 2"),
                    Text("Page 3"),
                    Text("Page 4")
                ], currentPage: $curPage)
            

        .edgesIgnoringSafeArea(.all)
    


struct TestView_Previews: PreviewProvider 
    static var previews: some View 
        TestView()
    

我不知道这是 SwiftUI 错误还是使用 UIViewControllerRepresentable 的副作用或什么。有其他人看到这个带有条件视图吗?关于解决方法的任何想法?

【问题讨论】:

问题解决了吗?我尝试了第一个答案,但没有成功=(,我被这个问题困住了,我正在尝试第一个索引 这个问题你解决了吗? 【参考方案1】:

我不知道这个问题的根本原因是什么。但我用两个嵌套的 VStack 解决了它。将您的 PageView 放在内部,并将您的 if 或其他视图放在外部 VStack 中。

VStack 
    if curPage == 9892832 
                Text("OK").padding().foregroundColor(.blue).padding(.top, 60)
    

    VStack 

        PageView([
                Text("Page 1"),
                Text("Page 2"),
                Text("Page 3"),
                Text("Page 4")
            ], currentPage: $curPage)
    


【讨论】:

以上是关于PageView (UIPageViewController) 的条件同级中断分页的主要内容,如果未能解决你的问题,请参考以下文章

PageView:禁用默认滚动并将其替换为 Tap 事件

如何在 Flutter 中创建垂直滚动的 PageView?

在垂直PageView中包装不同高度的项目 - Flutter

Flutter PageView 禁止滑动

Flutter - 如何制作 PageView 和 ListView?

在颤振中如何使带有平移手势的内部小部件不会与PageView冲突