WKWebView裝載H5頁面關(guān)閉頂部彈簧效果

摘要:著急要解決方案,直接滾到結(jié)尾復(fù)制有效代碼,即可。本文記錄了本人在解決這個(gè)過程的大致心路歷程,可以說是摸索的過程吧。拙筆耕耘,謝謝閱讀。

最近在項(xiàng)目中,遇到一個(gè)棘手的問題:webView裝載H5頁面,設(shè)置導(dǎo)航欄顏色和h5頁面保持一致的情況下,下拉h(huán)5頁面頂部會(huì)產(chǎn)生一個(gè)視覺斷層,這對用戶并不友好。于是開始了一系列的探索之路。

最初嘗試的解決方式:
設(shè)置WKWebView下的scrollView的屬性

webView.scrollView.bounces =false

// default NO. if YES and bounces is YES, even if content is smaller than bounds, allow drag vertically
webView.scrollView.alwaysBounceVertical = false //其實(shí)默認(rèn)也是false

但簡單的設(shè)置并不起作用。
于是從渲染層的效果看當(dāng)前的視圖層次,仔細(xì)扒拉發(fā)現(xiàn)當(dāng)前的渲染視圖層次里最上層裝載h5內(nèi)容的是一個(gè)WKChildScrollView ,這就tm的搞笑,是我漲了見識(shí)也是技術(shù)迭代的快啊,繼續(xù)探索,下意識(shí)就是既然我可以看到這個(gè)視圖,那就可以拿到這個(gè)對象進(jìn)行操作。只能說幼稚坦然暴露在在未知領(lǐng)域的面前,且即便有著龐大的數(shù)量基數(shù)。接下來,我通過webView.scrollView.subviews[0].subviews[0].subviews[0].subviews[0]這種方式獲取了5-6層的子View并且遍歷,然后并沒有拿到。打破了以前的這種求知路線的經(jīng)驗(yàn)。

接下來,向另一個(gè)路線尋找解決方案,從js代碼上入手,以前的工作經(jīng)驗(yàn)告訴我,webview是可以獲取到h5的上下文(JSContext),再通過“deocment.xxx.xxx...”獲取H5內(nèi)部控件元素。于是開啟了更多偏向js層面與原生交互的學(xué)習(xí)探索,進(jìn)行猛烈的炮火攻擊,搜羅了市面的大多數(shù)webView與js的中文文章(少量的類似問題的英文文檔),在不斷加深對webview的理解中,我有一個(gè)深刻意識(shí),可以用js解決了這個(gè)問題。

果然搜到了很多解決方案,例如解決H5頁面在iOS系統(tǒng)中滑動(dòng)回彈效果(橡皮筋效果)導(dǎo)致的穿透問題此類眾多,或者集成一個(gè)貌似叫bounce的js庫解決,就是需要前端做集成修改的方案,然而事實(shí)證明,還在路上。繼續(xù)gank,終于,emmmm,上代碼

document.body.addEventListener('touchmove', function (e) {
              e.preventDefault();
            }, {passive: false});
            

效果很明顯,就是h5頁面直接不能滑動(dòng)。心里獨(dú)白就是這....就離譜。標(biāo)題打著已經(jīng)解決的旗號,結(jié)果是醫(yī)駝不?;畹姆桨浮W屛蚁肫鸩菰巷w奔的草泥馬,默默的一句“啊,呸”。
然后,繼續(xù)往JSValue這種線上摸,線太長,精力有限,消耗原動(dòng)力沒有產(chǎn)出,于是放棄了(識(shí)得前景大,不因一隅陷?。V饕钦伊饲岸私涣魈接?,加上前面的經(jīng)驗(yàn),我下意識(shí)回到了WKWebView的本身,

然后又在一個(gè)微信iOS群里拋出了這個(gè)問題,有伙伴,給出了以下的解決方案:

let firstTempList:[UIView] = webView.scrollView.subviews 
 let subTempList = firstTempList.first?.subviews ?? []
 subTempList.first?.backgroundColor = UIColor.grayF8()

copy+v+c之后,無法獲直接取的view顏色倒是可以設(shè)置,但還是不能,又加上了

webView.scrollView.isOpaque = true

個(gè)人測試是不能通過實(shí)現(xiàn)設(shè)置底色的方式,消去視覺斷層的問題的,但還是建議遇到類似問題嘗試下。

在上述依然不能解決問題的前提下,我想這就是寫博客的機(jī)會(huì)了(裝了裝了,就是感覺這樣的問題,解決方式不應(yīng)該沒有以及應(yīng)該說不上會(huì)很難,所以堅(jiān)持繼續(xù)探究的,一開始沒有想到寫此文章,真有文章解決,我是沒心浪費(fèi)精力寫的)。

到這里,也是過了一些時(shí)間了,牽強(qiáng)附會(huì)的扯上初心吧,又回到了當(dāng)初的獲取WKChildScrollView的方式。不甘心的又使用了webView.scrollView.subviews[0].subviews[0].subviews[0].subviews[0]這種方式,在未知的領(lǐng)域面前,幼稚不分對象。但是不甘讓人產(chǎn)生堅(jiān)持心,于是我決定把subview子類鏈走到底,慶幸每個(gè)subviews- item并不多啊,終于,終于,看下圖:(不要著急懵逼和嘆服取了足足10層)

12333333.jpg

于是,終于看到晨曦的光,于是進(jìn)行了下面的操作


000000.jpg

事情進(jìn)行到這,終于松了一口氣。目的地是已到達(dá),但多少還是跟完美有點(diǎn)距離。因?yàn)閕OS的系統(tǒng)版本不斷更新,這個(gè)解決方式只能算是解決了當(dāng)前版本的當(dāng)下場景的問題。而且,這樣的代碼作為上線代碼,顯然不行滴。直接強(qiáng)解包讀取危害太大,用fisrt或last替換也是太low,而且不能兼容各種場景。于是嘗試while循環(huán),條件是subview.count > 0。 所以gank,寫了幾句代碼,這......還不如來個(gè)遞歸吧。于是我的終極解決方案出來了,如下。(有一個(gè)缺點(diǎn)是所有的WebView的頁面的下拉的彈簧效果都被禁止了,稍后給出解決方案)

    func checkSubviewsIsContoinScrollView(v: UIView?) {
         v?.subviews.forEach({ itemV in            

                if itemV.isKind(of: UIScrollView.**self**), **let** childScrollV = itemV as? UIScrollView {
                
                childScrollV.bounces = **false**
            }

            self.checkSubviewsIsContoinScrollView(v: itemV)
        })
    }
    
         //調(diào)用的地方以及逐漸優(yōu)化
          checkSubviewsIsContoinScrollView(v: webView)

//        let childScrollView = webView.scrollView.subviews[0].subviews[0].subviews[0].subviews[0].subviews[0].subviews[0].subviews[1].subviews[0].subviews[0].subviews[0]
//        let WKChildScrollView: AnyClass? = NSClassFromString("WKChildScrollView")
//        if let WKChildScrollView = WKChildScrollView, childScrollView.isKind(of: WKChildScrollView.self) {
//        if let childScrollV = childScrollView as? UIScrollView {
//        childScrollV.bounces = false
//        }
//        }

//        if childScrollView.isKind(of: UIScrollView.self)  {
//            if let childScrollV = childScrollView as? UIScrollView {
//                childScrollV.bounces = false
//            }
//        }    

致此,方是柳暗花明又一村啊。

缺點(diǎn)一: 就是所有裝載的h5頁面的頂部彈簧效果都被禁了,這其實(shí)不友好。
解決方案一:寫一個(gè)BaseWebViewVC不實(shí)現(xiàn)上面的代碼,然后再繼承BaseWebViewVC寫一個(gè)BaseNoBounceWebViewVC,實(shí)現(xiàn)上述代碼。
解決方案二:可以直接通過獲取當(dāng)前導(dǎo)航欄是否有顏色,再結(jié)合js代碼獲取當(dāng)前h5頁面是否有背景的場景來判斷是否調(diào)用上述方法。

缺點(diǎn)二:
本人測試的存在數(shù)據(jù)加載緩慢的情況,而這段代碼并不工作(概率極小,但還需要優(yōu)化)。推測是因?yàn)閿?shù)據(jù)加載緩慢導(dǎo)致視圖層次渲染延遲,在viewDidAppear中,WKChildScrollView還沒有渲染生成的原因。期待大神給出這個(gè)的優(yōu)化的方案。

//有嘗試在此方法中調(diào)用,但是沒有效果,同時(shí)進(jìn)行延遲幾秒的調(diào)用有生效,那基本就閉環(huán)解決了。因?yàn)闇y試 case量少,不能保證。
func webView(webView: WKWebView, didFinish navigation: WKNavigation!)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容