0

I have horizontal scrolling in a webView. I need that my text in the webView to be shown from the position x = 1000. For this I use the following line:

self.webView.scrollView.contentOffset.x = 1000

The problem is that this line only works in the scrollViewDidScroll method, and if I use it in method, then after that I cannot scroll my webView because it is always on x = 1000

In viewDidLoad the line does not work. Where I need to write it so that it works at the start of webView, and then I can scroll my webView correctly.

code:

import UIKit
import WebKit

class ViewController: UIViewController, UIScrollViewDelegate {

    @IBOutlet weak var webView: WKWebView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        webView?.scrollView.delegate = self
        
        do {
            guard let filePath = Bundle.main.path(forResource: "index", ofType: "html")
                else {
                    print ("File reading error")
                    return
            }
            
            let headerString = "<meta name=\"viewport\" content=\"initial-scale=1.0\" />"
            let string =  try String(contentsOfFile: filePath, encoding: .utf8)
            let baseUrl = URL(fileURLWithPath: filePath)
            webView.loadHTMLString(headerString+string, baseURL: baseUrl)
            webView.scrollView.isPagingEnabled = true
            
            self.webView.scrollView.contentOffset.x = 1000
        }
        catch {
            print ("File HTML error")
        }
    }

}

This line also does not work in viewDidLoad

webView.scrollView.setContentOffset(CGPoint(x: 1000, y: 0), animated: false)
User
  • 121
  • 1
  • 2
  • 11
  • You need to wait until the web view has *finished* loading the content. See: https://developer.apple.com/documentation/webkit/wknavigationdelegate/1455629-webview – DonMag Sep 18 '20 at 19:52
  • @DonMag I add this `func webView(_ webView: WKWebView, didFinish navigation:WKNavigation!) { self.webView.scrollView.contentOffset.x = 700 }` but function not called – User Sep 18 '20 at 20:16

1 Answers1

3

I assume that - because a lot goes on when a WKWebview loads, formats, and displays html - it's not going to be quite as straightforward as you might hope.

Couple approaches that I've found playing around with this...

First, in order to get didFinish navigation to be called, make sure your controller conforms to WKNavigationDelegate:

class ViewController: UIViewController, WKNavigationDelegate { }

and, set the web view's delegate to self in viewDidLoad():

webView.navigationDelegate = self

Then, two options...

Option 1 -- Animate the Offset. I don't know your needs, but this might work for you, and, it would inform the user that he's looking at an already-scrolled portion of the html:

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    webView.scrollView.setContentOffset(CGPoint(x: 1000, y: 0), animated: true)
}

Option 2 -- Delay setting the Offset. It seems we need a tiny delay, 0.01 seconds appears to work:

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
        webView.scrollView.contentOffset.x = 1000
    }
}

Depending on your actual html content, that may appear as an abrupt flicker, so...

Option 3 - Delay setting the Offset and then fade-in the view. In viewDidAppear() set webView.alpha = 0.0, and then:

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
        webView.scrollView.contentOffset.x = 1000
        UIView.animate(withDuration: 0.3, animations: {
            webView.alpha = 1.0
        })
    }
}
DonMag
  • 69,424
  • 5
  • 50
  • 86
  • The code worked fine at first time. But over time, I noticed that sometimes the text from the `webView` is loaded from the first page. Instead of showing the last page that user stopped reading. Delay doesn't always help. If I use `Option 3` and make the delay value higher, 0.2 I see like at first, loading my first page and next `scrollview.webView` goes to the last reading page very quickly. I am trying to create something like a reading controller in the Apple Books app. I save `contentOffset.x` value and when the user open app again I show the page where user stopped reading the last time. – User Sep 22 '20 at 22:51
  • Hello! pleas check this question - https://stackoverflow.com/questions/64561831/load-html-text-in-wkwebview these questions are related and no one can help me figure it out – User Oct 29 '20 at 15:56