防止網(wǎng)頁(yè)在微信中下拉露黑底方案調(diào)研

問題

如果用微信打開網(wǎng)頁(yè),如果我們?cè)诰W(wǎng)頁(yè)第一屏繼續(xù)下拉的情況下,頂部 webview 上部會(huì)有一塊黑底顯示出來,類似于原生 App 的下拉更新的樣子?,F(xiàn)在我們希望禁止這個(gè)行為。

分析

通過谷歌大法發(fā)現(xiàn),這個(gè)行為應(yīng)該是 touchmove 事件的默認(rèn)行為。要禁止這個(gè)黑底出現(xiàn),只要監(jiān)聽 touchmove 事件,在其中 preventDefault() 即可。但是如果簡(jiǎn)單的禁止了 touchmove 事件的默認(rèn)行為,那么網(wǎng)頁(yè)本身就無法進(jìn)行上下滾動(dòng)。那么我們是不是可以檢測(cè)當(dāng)前網(wǎng)頁(yè)是否已經(jīng)滾動(dòng)到最上部,如果滾動(dòng)到了最上面(無法繼續(xù)下拉)那么我們?cè)俳?touchmove 的默認(rèn)行為。

解決方案

我們假設(shè)頁(yè)面有一個(gè)容器 div#wrapper,它負(fù)責(zé)整個(gè)頁(yè)面的滾動(dòng)。為什么不用 body,因?yàn)楣雀璐蠓ǜ嬖V我,有的版本的瀏覽器會(huì)不讓 js 去禁止 body touchmove 的默認(rèn)行為。所以我們大致的代碼如下:

var wrapper = document.getElementById( 'wrapper' );
var touchstartY;

wrapper.addEventListener( 'touchstart', function (ev) {
    var events = ev.touches[ 0 ] || ev;
    touchstartY = events.clientY;
}, false );

wrapper.addEventListener( 'touchmove', function (ev) {
    var events = ev.touches[ 0 ] || ev;
    // 下拉時(shí)并且頁(yè)面已經(jīng)到頂部時(shí)
    if ( events.clientY > touchstartY && (wrapper.scrollTop === 0) ) {
      ev.preventDefault();
    }
}, false );

我在 ios10 上測(cè)試成功,但是在榮耀8 的 EMUI5(Android7)系統(tǒng)上則有一種情況還是會(huì)出現(xiàn)黑底,就是當(dāng)頁(yè)面位置在即將到頂部但是還有一段距離,用戶開始下拉,那么當(dāng)頁(yè)面滾到頂部時(shí)用戶不放手繼續(xù)下拉,則依然會(huì)出現(xiàn)黑底。我原先以為是 touchmove 觸發(fā)的頻率過低所致,所以我故意慢一點(diǎn)拉然后記錄各個(gè)變量的值,我發(fā)現(xiàn)在 touchmove 時(shí)即使events.clientY >= touchstartY && (wrapper.scrollTop === 0)這個(gè)條件為true了,我停頓一下手指再繼續(xù)往下拉(停頓時(shí)候手指不離開屏幕)依然會(huì)出現(xiàn)黑底,意味著這種情況下 preventDefault() 沒能阻止黑底的出現(xiàn)。那我此時(shí)基本可以認(rèn)為這是微信 webview 在 android 上的一個(gè) bug。

然后我找了另一種方案來禁止?jié)L動(dòng)就是當(dāng)wrapper.scrollTop === 0時(shí)候,給 wrapper 添加 touch-action: none;的樣式,依然不能解決這個(gè)問題。所以經(jīng)過一天的調(diào)研,暫時(shí)只能在水果機(jī)的微信上實(shí)現(xiàn)這個(gè)功能。

最后水果機(jī)微信的 webview 在頁(yè)面滾動(dòng)到最底部繼續(xù)上拉的情況也會(huì)出現(xiàn)黑底,那么我們?cè)诙嗉右粋€(gè)判斷,最終的代碼初稿如下:

var wrapper = document.getElementById( 'wrapper' );
var touchstartY;

wrapper.addEventListener( 'touchstart', function (ev) {
    var events = ev.touches[ 0 ] || ev;
    touchstartY = events.clientY;
}, false );

wrapper.addEventListener( 'touchmove', function (ev) {
    var events = ev.touches[ 0 ] || ev;
    var scrollTop = wrapper.scrollTop,
        var offsetHeight = wrapper.offsetHeight,
        var scrollHeight = wrapper.scrollHeight;
    if ( events.clientY > touchstartY && (wrapper.scrollTop === 0) ) {
    // 下拉時(shí)并且頁(yè)面已經(jīng)到頂部時(shí)
      ev.preventDefault();
    } else if ( events.clientY < touchstartY && (scrollTop + offsetHeight >= scrollHeight) ) {
    // 上拉時(shí)并且頁(yè)面已經(jīng)到底部時(shí)
      ev.preventDefault();
    }
}, false );

后記

我初次接觸移動(dòng)端,以上是我個(gè)人的調(diào)研結(jié)果,不排除有成熟的原生解決方案(當(dāng)然如果用 IScroll 模擬滾動(dòng)是可以解決這個(gè)問題的)。如果有有經(jīng)驗(yàn)的同志,希望不惜賜教。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,231評(píng)論 25 708
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,438評(píng)論 4 61
  • 我搖著車在街上慢慢走,不急著回家。人有時(shí)候只想獨(dú)自靜靜地待一會(huì)。悲傷也成享受。 ...
    一只甜橙橙閱讀 1,976評(píng)論 0 1
  • Description: You are given two non-empty linked lists rep...
    Icytail閱讀 228評(píng)論 0 0
  • 感謝神給我服侍兩位院士的機(jī)會(huì),在看到很多優(yōu)秀的習(xí)慣的時(shí)候,我越來越覺得,優(yōu)秀的人是蒙上帝祝福的,上帝會(huì)在專注的時(shí)候...
    沐澄_閱讀 991評(píng)論 0 0

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