徹底解決IOS HTML頁面上游標跳行、游標不跟隨頁面問題
宣告:這裡只是說明一種處理方法
繼上一篇文章,處理IOS滑動時,游標不跟隨頁面滾動,處理方法是,監聽touchmove事件,獲取當focus的元素,使之失去游標;但是這種方法並不能真正的解決問題,比如,你進入頁面,並不滑動頁面,而是去點選螢幕可見區域最底下的輸入框時,問題就出來了,如圖:
這裡說一下,網路上大多說是IOS上fixed定位,修改定位為absolute;或者是新增fastclick.js庫,加速手機上tap事件的響應;
問題就出在這裡,你確定你的頁面是定位的因素?你確定添加了fastclick庫就可以了?如果嘗試了上面兩種方法還不行,你可以接著往下看;
仔細觀察頁面,當你點選最後一行輸入框時、滑動頁面時,或者是彈框;你可以看到頁面上的活動元素先聚焦再滾動;也就是說,activate元素的聚焦事件在頁面滾動之前或者滾動完成之前就已經完成了,所以這時候頁面滾動,而游標又不跟隨滾動,就造成了游標跳行、錯亂的問題。
解決方法:
一、輸入框在聚焦的時候,會彈起軟鍵盤;所以,我們監聽軟鍵盤彈起事件,在彈起事件後,進行dom重繪,但是這種必須要加延時,程式碼如下:
document.body.addEventListener('focusin', function () { //軟鍵盤彈起事件 var node = document.activeElement; //當前focus的dom元素 setTimeout(function () { if (node) { if (node.nodeName == "TEXTAREA" || node.nodeName == 'INPUT') { //如果是input或textarea if (node.style.textShadow === '') { node.style.textShadow = 'rgba(0,0,0,0) 0 0 0'; //改變某個不可見樣式,觸發dom重繪 } else { node.style.textShadow = ''; } } } }, 1000); });
二、監聽螢幕滾動事件;是螢幕滾動,不是手指滑動的事件,因為我這裡使用的是sencha Touch移動端框架,所以,可能會不適應,但是道理是一樣的;程式碼如下:
initialize: function () { var me = this; me.callParent(); me.element.on({ submit: 'onSubmit', scope: me }); var scrollable = this.getInitialConfig().scrollable; if (scrollable == null || scrollable == false) { this.isScrollable = false; } else { this.isScrollable = true; } //新增scroll事件監聽 me.getScrollable().getScroller().on({ scroll: 'onScroll', scope: me }); }, //新增scroll事件響應函式 onScroll: function () { var node = document.activeElement; //當前focus的dom元素 if (node) { if (node.nodeName == "TEXTAREA" || node.nodeName == 'INPUT') { //如果是input或textarea if (node.style.textShadow === '') { node.style.textShadow = 'rgba(0,0,0,0) 0 0 0'; //改變某個不可見樣式,觸發dom重繪 } else { node.style.textShadow = ''; } } } },
這裡是修改sencha Touch formpanel容器的原始碼,添加了事件的監聽
對於第二個方法,如果你使用的是其他的框架,同樣的你需要做一些修改。但是道理是一樣的
三、理論,未實現;同樣是監聽螢幕滾動事件,使用定時器,實時監聽該頁面scrollTop,如果scrollTop在改變,那麼就說明頁面在滾動,如果在滾動,就獲取當前頁面activate元素,使之重繪
最後說一下,為什麼不能監聽touchmove事件,因為我們在滑動螢幕時,並不是手指離開了螢幕,螢幕就停止滾動了,螢幕還會有一個關心滾動存在;所以,單單是監聽touchmove並不能解決游標錯亂、跳行問題。除非,當你手指離開時,螢幕立馬停止滾動。所以還是監聽螢幕滾動最為靠譜
補充:如果你在touchmove中處理了游標不跟隨,也就是move時取消游標聚焦;這裡你可以將touchmove註釋掉,因為監聽scroll處理後,游標便會跟隨頁面滾動