wkwebview与nsscrollview中添加在SwiftUi中时不调整大小

发布于 2025-02-05 16:38:44 字数 3176 浏览 3 评论 0原文

swiftui中添加自定义nsscrollview,在wkwebview hstack内部添加到通过nshostingview

wkwebview无法正确完成全屏 边缘) child.translatesautoresizingmaskIntoconstraints = false,如果我跳过了 全屏正常工作,但是autoLayout因此无法正常工作。

     struct ContentView: View {
      var body: some View {
        VStack {
            ScrollViewX {
                HStack {
   
                    WebViewX()
                    .frame(width: 300, height: 300)
           
                }
            }
            .frame(width: 500, height : 500)
            
        }.frame(width: 700, height : 700)
    }
    }



    struct ScrollViewX<Content : View>: NSViewRepresentable {
    let content: Content

    init(@ViewBuilder content: () -> Content) {
        self.content = content()
    }

    func makeNSView(context: Context) -> CustomScrollView {
        let view = CustomScrollView(frame: .zero)
        let child = NSHostingView(rootView: content)
        child.translatesAutoresizingMaskIntoConstraints = false
        view.documentView = child
       child.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
       child.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

        return view
    }

    func updateNSView(_ nsView: CustomScrollView, context: Context) {
    }
     }

     class CustomScrollView: NSScrollView {
    
     override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
        self.drawsBackground = false
        self.hasHorizontalScroller = true
        self.hasVerticalScroller = false
        
        self.translatesAutoresizingMaskIntoConstraints = false
    }
        
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }

    }

     struct WebViewX: NSViewRepresentable {

    
    func makeNSView(context: Context) -> customWebView {
        let webView = customWebView(url: nil)
        return webView
    }
        
    func updateNSView(_ NSView: customWebView, context: Context) {
    }
     }

    class customWebView : WKWebView {
    convenience init(url : String?) {
        

        let config = WKWebViewConfiguration()
        
        config.limitsNavigationsToAppBoundDomains = false
        config.preferences.isTextInteractionEnabled = true
        config.preferences.setValue(true, forKey: "fullScreenEnabled")
        config.preferences.javaScriptCanOpenWindowsAutomatically = true
        config.defaultWebpagePreferences.allowsContentJavaScript = true
        self.init(frame: .zero, configuration : config)

        self.allowsBackForwardNavigationGestures = false
        self.allowsMagnification = true
        
        self.translatesAutoresizingMaskIntoConstraints = false

        let req = URLRequest(url: URL(string: "https://www.youtube.com")!)
        
        self.load(req)

    }
    
    convenience required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
     }

Adding a custom NSScrollView into SwiftUI, there is a WKWebview inside a HStack which is added to NSScrollView via NSHostingView

The WKWebview doesn't go fullscreen properly (doesnt resize and sticks to the leading
edge) when
child.translatesAutoresizingMaskIntoConstraints = false, if I skip this then the
fullscreen works as normal however the AutoLayout won't work because of this.

     struct ContentView: View {
      var body: some View {
        VStack {
            ScrollViewX {
                HStack {
   
                    WebViewX()
                    .frame(width: 300, height: 300)
           
                }
            }
            .frame(width: 500, height : 500)
            
        }.frame(width: 700, height : 700)
    }
    }



    struct ScrollViewX<Content : View>: NSViewRepresentable {
    let content: Content

    init(@ViewBuilder content: () -> Content) {
        self.content = content()
    }

    func makeNSView(context: Context) -> CustomScrollView {
        let view = CustomScrollView(frame: .zero)
        let child = NSHostingView(rootView: content)
        child.translatesAutoresizingMaskIntoConstraints = false
        view.documentView = child
       child.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
       child.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

        return view
    }

    func updateNSView(_ nsView: CustomScrollView, context: Context) {
    }
     }

     class CustomScrollView: NSScrollView {
    
     override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
        self.drawsBackground = false
        self.hasHorizontalScroller = true
        self.hasVerticalScroller = false
        
        self.translatesAutoresizingMaskIntoConstraints = false
    }
        
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }

    }

     struct WebViewX: NSViewRepresentable {

    
    func makeNSView(context: Context) -> customWebView {
        let webView = customWebView(url: nil)
        return webView
    }
        
    func updateNSView(_ NSView: customWebView, context: Context) {
    }
     }

    class customWebView : WKWebView {
    convenience init(url : String?) {
        

        let config = WKWebViewConfiguration()
        
        config.limitsNavigationsToAppBoundDomains = false
        config.preferences.isTextInteractionEnabled = true
        config.preferences.setValue(true, forKey: "fullScreenEnabled")
        config.preferences.javaScriptCanOpenWindowsAutomatically = true
        config.defaultWebpagePreferences.allowsContentJavaScript = true
        self.init(frame: .zero, configuration : config)

        self.allowsBackForwardNavigationGestures = false
        self.allowsMagnification = true
        
        self.translatesAutoresizingMaskIntoConstraints = false

        let req = URLRequest(url: URL(string: "https://www.youtube.com")!)
        
        self.load(req)

    }
    
    convenience required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
     }

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

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

发布评论

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

评论(2

原野 2025-02-12 16:38:44

所有条件仍然不清楚,但实际上它是水平滚动器,因此高度肯定可以是约束,但是对于内容...每个视图都必须定义某个宽度(或至少有一些规则需要计算)。任何其他硬码都应被删除。

因此,在下面的情况下,所有更改所有屏幕都按预期自动全屏工作(用Xcode 13.4/MacOS 12.4测试)

// in main: 

        VStack {
            ScrollViewX {
                HStack {
                    WebViewX(url: "https://www.apple.com")
                        .frame(width: 500)
                    WebViewX(url: "https://www.google.com")
                        .frame(width: 500)
                    WebViewX(url: "https://www.stackoverflow.com")
                        .frame(width: 500)
                    WebViewX()
                        .frame(width: 500)
                }
            }
        }
    }

// in ScrollViewX:

    func makeNSView(context: Context) -> CustomScrollView {
        let view = CustomScrollView(frame: .zero)
        let child = NSHostingView(rootView: content)
        child.translatesAutoresizingMaskIntoConstraints = false
        view.documentView = child
        child.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        child.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

        // this one !!
        child.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true
        return view
    }

完整的测试代码在这里

All conditions still not clear, but actually it is horizontal scroller, so height definitely can be constraint, but for content... every view have to have some width defined (or at least have some rule to calculate). Any other hardcodes should be removed.

Thus with below changes all works in full screen as expected automatically (tested with Xcode 13.4 / macOS 12.4)

demo

// in main: 

        VStack {
            ScrollViewX {
                HStack {
                    WebViewX(url: "https://www.apple.com")
                        .frame(width: 500)
                    WebViewX(url: "https://www.google.com")
                        .frame(width: 500)
                    WebViewX(url: "https://www.stackoverflow.com")
                        .frame(width: 500)
                    WebViewX()
                        .frame(width: 500)
                }
            }
        }
    }

// in ScrollViewX:

    func makeNSView(context: Context) -> CustomScrollView {
        let view = CustomScrollView(frame: .zero)
        let child = NSHostingView(rootView: content)
        child.translatesAutoresizingMaskIntoConstraints = false
        view.documentView = child
        child.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        child.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

        // this one !!
        child.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true
        return view
    }

Complete test code is here

旧时模样 2025-02-12 16:38:44

在@asperi @asperi中解决了

问题,因此当您在AppKit中添加nshostingview()时,webviewx()上的frame()归功于

SwiftUI框架修饰符在FullScreen期间禁用调整大小的视图。

解决方案是在WillenterFullscreen和Exitfullscreen通知上更改帧()。

也许使用自动划分有更好的解决方案

Solved it thanks to @Asperi

The issue is due to the frame() on WebViewX()

When you add a NSHostingView() in Appkit the SwiftUI frame modifier disables the view from resizing during fullscreen.

The solution is to change the frame() on willEnterFullscreen and exitFullscreen notifications.

Maybe there are better solutions using Auto-layout

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