nachonavarro / Pages

📖 A lightweight, paging view solution for SwiftUI
MIT License
586 stars 55 forks source link

WebView in Pages #11

Open halilyuce opened 4 years ago

halilyuce commented 4 years ago

Hello again :)

I want to load each news inside of pages, I am loading Html content in wkwebview and I added it to the inside of pages. When I move to the next page webview height is the same as the previous one, does not load with new height.

What do you recommend to solve this issue ? Thanks in advance :)

WebTest View

import SwiftUI
import Pages

struct WebTest: View {

    @ObservedObject var viewModel = NewsVM()
    @State var index: Int = 0
    @State var newID: String = ""
    let screen = UIScreen.main.bounds
    let formatString = "<html><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0\"><script type=\"text/javascript\" src=\"https://platform.twitter.com/widgets.js\"></script><style>@media (prefers-color-scheme: dark) { body { background-color: #1c1c1e; color: white; }} img,iframe,blockquote {\n\t\t\tmax-width: \(UIScreen.main.bounds.width - 24);\n\t\t\theight: auto\n\t\t}\n\t\t</style></head><body><span style=\"font-family: '-apple-system', 'HelveticaNeue'; font-size:17\">%@</span></body></html>"
    @State private var webViewHeight: CGFloat = .zero

    init(id:String) {
        viewModel.fetchNews(id: id)
        self.newID = id
    }

    var body: some View {
        Group{
            if self.viewModel.news.count > 0 {
                ModelPages(viewModel.news, currentPage: $index, wrap: false, hasControl: false) { pageIndex, new in
                    ScrollView(.vertical, showsIndicators: false){
                            Text(new.title)
                                .font(.title).fontWeight(.bold)
                                .padding(.horizontal)
                                .fixedSize(horizontal: false, vertical: true)
                            Text("Height: \(self.webViewHeight)").padding()
                            WebView(htmlString: String(format: self.formatString, new.content), dynamicHeight: self.$webViewHeight)
                                .frame(width: self.screen.width - 16, height: self.webViewHeight)
                                .padding(.horizontal, 8)
                        }
                    }
            }else{
                Group{
                    if self.viewModel.error == true{
                        ConnectionError()
                    }else{
                        LoadingView()
                    }
                }
            }
        }
    }
}

WebView

import SwiftUI
import Webkit

struct WebView: UIViewRepresentable {
    var htmlString: String
    @Binding var dynamicHeight: CGFloat
    var webView: WKWebView = WKWebView()

    func makeUIView(context: Context) -> WKWebView {
        webView.navigationDelegate = context.coordinator
        webView.scrollView.bounces = false
        webView.backgroundColor = .clear
        if htmlString != context.coordinator.content {
            context.coordinator.content = htmlString
            webView.loadHTMLString(htmlString, baseURL: Bundle.main.bundleURL)
        }
        return webView
    }

    func updateUIView(_ uiView: WKWebView, context: Context) {
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, WKNavigationDelegate {
        var parent: WebView
        var content = ""

        init(_ parent: WebView) {
            self.parent = parent
        }

        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            webView.evaluateJavaScript("document.readyState", completionHandler: { (complete, error) in
                if complete != nil {
                   webView.evaluateJavaScript("document.documentElement.scrollHeight", completionHandler: { (height, error) in
                        DispatchQueue.main.async{
                            self.parent.dynamicHeight = height as? CGFloat ?? 0
                        }
                    })
                }
            })
        }
    }
}

First content height is true, but the second view still using same height

First Page image

Second Page image

nachonavarro commented 4 years ago

Hey! Could you replicate a minimal example of this without the SDWebImageSwiftUI dependency so I can test this?

halilyuce commented 4 years ago

@nachonavarro hello, SDWebImage is not needed now :) I found what causes to it. When the previous content height is smaller than the next one, it's working well but when it's bigger than next one it's not changing height value. Interesting but I don't have any idea how can I fix it. I researched it on google and StackOverflow but I could not find any solution for it.