为UiviewRementable ScrollView(SwiftUi)设置ContentOffset

发布于 2025-01-29 19:38:48 字数 3444 浏览 4 评论 0原文

问题

我正在尝试使用给定的缩放和位置启动UiviewSrentable scrollview的

。我在MakeUiview中设置了新的Zoom和新的ContentOffset,但是SetContentOffset调用没有视觉效果,并且在从新的Zoom中重新放大时,ScrollView会移动内容,就好像SetContentOffSet一样效果

我在做什么错?

下面的代码

是uiviewermesentable的整个代码。我标记了最相关的行,并带有“请参阅此处”评论。

import SwiftUI

struct ZoomableScrollView<Content: View>: UIViewRepresentable {
    @EnvironmentObject var drawingModel: DrawingModel
    private var content: Content
    let screenScale: CGFloat
    
    init(screenScale: CGFloat, @ViewBuilder content: () -> Content) {
        self.screenScale = screenScale
        self.content = content()
    }

    func makeUIView(context: Context) -> UIScrollView {
        // set up the UIScrollView
        let scrollView = UIScrollView()
        scrollView.delegate = context.coordinator  // for viewForZooming(in:)

        let fullPageZoomScale = 0.85 * screenScale // screenScale is a constant
        scrollView.maximumZoomScale = fullPageZoomScale * 10
        scrollView.minimumZoomScale = fullPageZoomScale
        scrollView.zoomScale = fullPageZoomScale
        scrollView.bouncesZoom = true
        scrollView.delaysContentTouches = false

        // create a UIHostingController to hold our SwiftUI content
        let hostedView = context.coordinator.hostingController.view!
        hostedView.translatesAutoresizingMaskIntoConstraints = true
        hostedView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        hostedView.frame = scrollView.bounds
        scrollView.addSubview(hostedView)
        
        /// -------- SEE HERE These two lines does not work as intended
        scrollView.setZoomScale(0.5319657829374683, animated: false)
        scrollView.setContentOffset(CGPoint(x: 518.5, y: 330.0), animated: false)
        /// -----
        
        return scrollView
    }

    func makeCoordinator() -> Coordinator {
        return Coordinator(hostingController: UIHostingController(rootView: self.content),
                           userScrolledAction: drawingModel.userScrollAction,
                           userZoomedAction: drawingModel.userZoomAction)
    }

    func updateUIView(_ uiView: UIScrollView, context: Context) {
        // update the hosting controller's SwiftUI content
        context.coordinator.hostingController.rootView = self.content
        assert(context.coordinator.hostingController.view.superview == uiView)
    }

    /// MARK: - Coordinator
    class Coordinator: NSObject, UIScrollViewDelegate {
        var hostingController: UIHostingController<Content>
        let userScrolledAction: (CGPoint) -> Void
        let userZoomedAction: (CGFloat) -> Void

        init(hostingController: UIHostingController<Content>, userScrolledAction: @escaping (CGPoint) -> Void, userZoomedAction: @escaping (CGFloat) -> Void) {
            self.hostingController = hostingController
            self.userScrolledAction = userScrolledAction
            self.userZoomedAction = userZoomedAction
        }

        func viewForZooming(in scrollView: UIScrollView) -> UIView? {
            return hostingController.view
        }

        func scrollViewDidScroll(_ scrollView: UIScrollView) {
            userScrolledAction(scrollView.contentOffset)
        }

        func scrollViewDidZoom(_ scrollView: UIScrollView) {
            userZoomedAction(scrollView.zoomScale)
        }
    }
}

Problem

I'm trying to start an UIViewRepresentable ScrollView with a given zoom and position.

I set the new zoom and new contentOffset in the makeUIView, but the setContentOffset call has no VISUAL effect and when zooming back out from the new zoom, the scrollview moves the content as if the setContentOffset had had effect.

What am I doing wrong?

Code

Below is the entire code for the UIViewRepresentable. I've marked the most relevant lines with a 'SEE HERE' comment.

import SwiftUI

struct ZoomableScrollView<Content: View>: UIViewRepresentable {
    @EnvironmentObject var drawingModel: DrawingModel
    private var content: Content
    let screenScale: CGFloat
    
    init(screenScale: CGFloat, @ViewBuilder content: () -> Content) {
        self.screenScale = screenScale
        self.content = content()
    }

    func makeUIView(context: Context) -> UIScrollView {
        // set up the UIScrollView
        let scrollView = UIScrollView()
        scrollView.delegate = context.coordinator  // for viewForZooming(in:)

        let fullPageZoomScale = 0.85 * screenScale // screenScale is a constant
        scrollView.maximumZoomScale = fullPageZoomScale * 10
        scrollView.minimumZoomScale = fullPageZoomScale
        scrollView.zoomScale = fullPageZoomScale
        scrollView.bouncesZoom = true
        scrollView.delaysContentTouches = false

        // create a UIHostingController to hold our SwiftUI content
        let hostedView = context.coordinator.hostingController.view!
        hostedView.translatesAutoresizingMaskIntoConstraints = true
        hostedView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        hostedView.frame = scrollView.bounds
        scrollView.addSubview(hostedView)
        
        /// -------- SEE HERE These two lines does not work as intended
        scrollView.setZoomScale(0.5319657829374683, animated: false)
        scrollView.setContentOffset(CGPoint(x: 518.5, y: 330.0), animated: false)
        /// -----
        
        return scrollView
    }

    func makeCoordinator() -> Coordinator {
        return Coordinator(hostingController: UIHostingController(rootView: self.content),
                           userScrolledAction: drawingModel.userScrollAction,
                           userZoomedAction: drawingModel.userZoomAction)
    }

    func updateUIView(_ uiView: UIScrollView, context: Context) {
        // update the hosting controller's SwiftUI content
        context.coordinator.hostingController.rootView = self.content
        assert(context.coordinator.hostingController.view.superview == uiView)
    }

    /// MARK: - Coordinator
    class Coordinator: NSObject, UIScrollViewDelegate {
        var hostingController: UIHostingController<Content>
        let userScrolledAction: (CGPoint) -> Void
        let userZoomedAction: (CGFloat) -> Void

        init(hostingController: UIHostingController<Content>, userScrolledAction: @escaping (CGPoint) -> Void, userZoomedAction: @escaping (CGFloat) -> Void) {
            self.hostingController = hostingController
            self.userScrolledAction = userScrolledAction
            self.userZoomedAction = userZoomedAction
        }

        func viewForZooming(in scrollView: UIScrollView) -> UIView? {
            return hostingController.view
        }

        func scrollViewDidScroll(_ scrollView: UIScrollView) {
            userScrolledAction(scrollView.contentOffset)
        }

        func scrollViewDidZoom(_ scrollView: UIScrollView) {
            userZoomedAction(scrollView.zoomScale)
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

乱世争霸 2025-02-05 19:38:48

应该进入

func updateUIView(_ uiView: UIScrollView, context: Context)

should move into

func updateUIView(_ uiView: UIScrollView, context: Context)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文