UIPageViewController 中的 SwiftUI scrollViewDidScroll 无法正常工作 [英] SwiftUI scrollViewDidScroll in UIPageViewController not work properly
问题描述
我关注了 Apple 的关于 interifying-with-uikit 的 SwiftUI 教程,我想得到 UIScrollView
的 contentOffset
,所以我在 PageViewController
中定义了@Binding var progress: CGFloat
,但在 scrollViewDidScroll
中,PageViewController
在我设置时将无法正常工作self.parent.progress = progress
.
I followed Apple's SwiftUI tutorial about interfacing-with-uikit,I want to get the contentOffset
of UIScrollView
,so I then defined@Binding var progress: CGFloat
in PageViewController
,but in the scrollViewDidScroll
,PageViewController
will not work correctly when I set
self.parent.progress = progress
.
行为是当我滑动PageViewController
时,它会自动返回.
The behavior is when I slide the PageViewController
, it will automatically go back.
当我将 @Binding var progress: CGFloat
更改为 @State var progress: CGFloat
时,PageViewController
将起作用,但我需要的是@Binding
而不是 @State
When I change @Binding var progress: CGFloat
to @State var progress: CGFloat
, PageViewController
will work ,but what I need is @Binding
rather than @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])
}
}
推荐答案
移动 setViewControllers
到创建位置,如下图
Move setViewControllers
to place of creation, like below
...
pageViewController.setViewControllers( // << here !!
[controllers[currentPage]], direction: .forward, animated: true)
return pageViewController
}
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {
}
经过测试适用于 Xcode 11.2/iOS 13.2
Tested & works with Xcode 11.2 / iOS 13.2
这篇关于UIPageViewController 中的 SwiftUI scrollViewDidScroll 无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!