iOS WKWebView обнаруживает, когда достигает дна - PullRequest
0 голосов
/ 18 октября 2018

У меня проблема с миграцией из UIViewView в WKWebView, обнаружение прокрутки достигло дна при использовании WKWebView.До WKWebView я использовал UIScrollViewDelegate, определяющий, видел ли пользователь весь контент, прокручивая его до конца WebView.Если он это сделал, кнопка «Подтвердить» была включена. iPhone - зная, достиг ли UIScrollView вершины или низа

Теперь с WKWebView это больше не работает.Я предполагаю, что причина в том, что при использовании WKWebView и загрузке html-строки он уменьшает представление для полной видимости контента.Поэтому мне пришлось установить область просмотра, добавив его в строку HTML.Это отображает содержимое таким же образом, как это делал UIWebView, предоставляя строку html, не устанавливая область просмотра.

Но теперь UIScrollViewDelegate при загрузке всегда сообщает, что дно уже достигнуто.Я предполагаю, что WKWebView загружает html, масштабирует его с полной видимостью, scrollViewDelegate распознает, что контент был полностью видимым, после этого появляется окно просмотра и масштабирует страницу, поэтому для отображения всего контента требуется вертикальная прокрутка.,Но в настоящее время моя кнопка «Подтвердить» уже включена.

Фрагмент кода

override func scrollViewDidScroll(_ scrollView: UIScrollView){
    let scrollViewHeight = scrollView.frame.size.height;
    let scrollContentSizeHeight = scrollView.contentSize.height;
    let scrollOffset = scrollView.contentOffset.y;
    if (scrollOffset + scrollViewHeight == scrollContentSizeHeight)
    {
        self.confirmButton.isEnabled = true; 
    }
}

С WKWebView scrollContentSizeHeight всегда совпадает с scrollViewHeight при загрузке, но после того, как функция делегата scrollViewDidScroll вызывает несколько раз (без прокрутки)scrollContentSizeHeight больше, чем scrollViewHeight в реальном размере.

Ответы [ 4 ]

0 голосов
/ 03 июня 2019

Создайте ScrollView внутри класса, WKWebView имеет встроенный вид прокрутки, сделайте созданный вами вид прокрутки относительно встроенного scrollview и реализуйте метод:

func scrollViewDidScroll(_ scrollView: UIScrollView){
    if (scrollView.contentOffset.y + 1) >= (scrollView.contentSize.height - scrollView.frame.size.height) {
        //bottom reached
        your code here

    }
}

, а затем сделайте свой класс наследуемым от UIScrollViewDelegate:

класс: UIViewController,

0 голосов
/ 19 октября 2018

Я написал расширение scrollview для Wkwebview, которое используется для чтения кода javascript. Через это вы можете использовать, чтобы проверить доступность веб-просмотра до конца страницы или нет.Перед использованием установите делегат веб-просмотра прокрутки.

extension BaseWebViewController: UIScrollViewDelegate {
func scrollViewDidEndDragging(_ scrollView: UIScrollView,
                                       willDecelerate decelerate: Bool) {
    webView.evaluateJavaScript("document.readyState", completionHandler: { (complete, error) in
        if complete != nil {
            self.webView.evaluateJavaScript("document.body.scrollHeight", completionHandler: { (height, error) in
                let bodyScrollHeight = height as! CGFloat
                var bodyoffsetheight: CGFloat = 0
                var htmloffsetheight: CGFloat = 0
                var htmlclientheight: CGFloat = 0
                var htmlscrollheight: CGFloat = 0
                var wininnerheight: CGFloat = 0
                var winpageoffset: CGFloat = 0
                var winheight: CGFloat = 0

                //body.offsetHeight
                self.webView.evaluateJavaScript("document.body.offsetHeight", completionHandler: { (offsetHeight, error) in
                    bodyoffsetheight = offsetHeight as! CGFloat

                    self.webView.evaluateJavaScript("document.documentElement.offsetHeight", completionHandler: { (offsetHeight, error) in
                        htmloffsetheight = offsetHeight as! CGFloat

                        self.webView.evaluateJavaScript("document.documentElement.clientHeight", completionHandler: { (clientHeight, error) in
                            htmlclientheight = clientHeight as! CGFloat

                            self.webView.evaluateJavaScript("document.documentElement.scrollHeight", completionHandler: { (scrollHeight, error) in
                                htmlscrollheight = scrollHeight as! CGFloat

                                self.webView.evaluateJavaScript("window.innerHeight", completionHandler: { (winHeight, error) in
                                    if error != nil {
                                        wininnerheight = -1
                                    } else {
                                        wininnerheight = winHeight as! CGFloat
                                    }

                                    self.webView.evaluateJavaScript("window.pageYOffset", completionHandler: { (winpageOffset, error) in
                                        winpageoffset = winpageOffset as! CGFloat

                                        let docHeight = max(bodyScrollHeight, bodyoffsetheight, htmlclientheight, htmlscrollheight,htmloffsetheight)

                                        winheight = wininnerheight >= 0 ? wininnerheight : htmloffsetheight
                                        let winBottom = winheight + winpageoffset
                                        if (winBottom >= docHeight) {
                                            print("end scrolling")
                                        }
                                    })

                                })

                            })

                        })

                    })
                })


            })
        }

    })

}
}

После того, как прокрутка дойдет до конца, вы увидите в консоли «конец прокрутки»

0 голосов
/ 22 октября 2018
func updateButtonState(_ scrollView : UIScrollView){
    if isURLLoaded {
        if scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height) {
            confirmButton.isEnabled = true
        } else if scrollView.contentOffset.y < scrollView.contentSize.height {
            confirmButton.isEnabled = false
        }
    }
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    self.updateButtonState(scrollView); 

}

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {

    isURLLoaded = true
    DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500), execute:{       
        self.updateButtonState(webView.scrollView)
    });

}

К сожалению, я не могу найти обратный вызов, когда scrollView готов к оценке, поэтому я установил тайм-аут 500 мс, с этой модификацией он работает как положено

0 голосов
/ 18 октября 2018

Но теперь UIScrollViewDelegate при загрузке всегда сообщает, что дно уже достигнуто.

В данном случае проблема заключается в том, что UIScrollView делегат вызывается до загрузки WKWebView.полностью.

Возьмите одну частную переменную экземпляра, чтобы проверить, полностью ли загружена URL.

var isURLLoaded = false

Подтвердите делегирование WKWebView вашему viewController.

webView.scrollView.delegate = self
webView.navigationDelegate = self

И переопределить эти методы делегата:

func scrollViewDidScroll(_ scrollView: UIScrollView) {

    if isURLLoaded {
        if scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height) {
            confirmButton.isEnabled = true
        } else if scrollView.contentOffset.y < scrollView.contentSize.height {
            confirmButton.isEnabled = false
        }
    }
}

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {

    isURLLoaded = true
}
...