UIPageViewController 中的 SwiftUI scrollViewDidScroll 无法正常工作
Posted
技术标签:
【中文标题】UIPageViewController 中的 SwiftUI scrollViewDidScroll 无法正常工作【英文标题】:SwiftUI scrollViewDidScroll in UIPageViewController not work properly 【发布时间】:2020-03-10 16:14:06 【问题描述】:我按照Apple的关于interfacing-with-uikit的SwiftUI教程,我想得到UIScrollView
的contentOffset
,所以我在PageViewController
中定义了@Binding var progress: CGFloat
,但在scrollViewDidScroll
,PageViewController
中不会当我设置时正常工作
self.parent.progress = progress
.
行为是当我滑动PageViewController
时,它会自动返回。
当我将@Binding var progress: CGFloat
更改为@State var progress: CGFloat
时,PageViewController
将起作用,但我需要的是@Binding
而不是@State
这是完整的代码
import SwiftUI
import UIKit
struct ContentView: View
var body: some View
PageView([Color.red,Color.green,Color.yellow])
struct ContentView_Previews: PreviewProvider
static var previews: some View
ContentView()
struct PageViewController: UIViewControllerRepresentable
var controllers: [UIViewController]
@Binding var currentPage: Int
@Binding var progress : CGFloat
func makeCoordinator() -> Coordinator
Coordinator(self)
func makeUIViewController(context: Context) -> UIPageViewController
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .horizontal)
pageViewController.dataSource = context.coordinator
for view in pageViewController.view.subviews
if view is UIScrollView
(view as! UIScrollView).delegate = context.coordinator
return pageViewController
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context)
pageViewController.setViewControllers(
[controllers[currentPage]], direction: .forward, animated: true)
class Coordinator: NSObject, UIPageViewControllerDataSource, UIPageViewControllerDelegate ,UIScrollViewDelegate
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 parent.controllers.last
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 parent.controllers.first
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
func scrollViewDidScroll(_ scrollView: UIScrollView)
let width = scrollView.frame.size.width
let offsetX = scrollView.contentOffset.x
let progress = (offsetX - width) / width
self.parent.progress = progress
struct PageView<Page: View>: View
var viewControllers: [UIHostingController<Page>]
@State var currentPage = 0
@State var progress : CGFloat = 0
init(_ views: [Page])
self.viewControllers = views.map UIHostingController(rootView: $0)
var body: some View
VStack
PageViewController(controllers: viewControllers, currentPage: $currentPage,progress: $progress)
struct PageView_Previews: PreviewProvider
static var previews: some View
PageView([Color.red])
【问题讨论】:
【参考方案1】:将setViewControllers
移动到创建位置,如下所示
...
pageViewController.setViewControllers( // << here !!
[controllers[currentPage]], direction: .forward, animated: true)
return pageViewController
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context)
经过测试并适用于 Xcode 11.2 / ios 13.2
【讨论】:
以上是关于UIPageViewController 中的 SwiftUI scrollViewDidScroll 无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章
UIPageViewController 中的 UIScrollView 滚动了多少?
如何删除 UIPageViewController 中的 previousViewControllers
UIPageViewController 中的脊椎到底是啥?