1. 程式人生 > >徹底解決IOS HTML頁面上游標跳行、游標不跟隨頁面問題

徹底解決IOS HTML頁面上游標跳行、游標不跟隨頁面問題

 

繼:修復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處理後,游標便會跟隨頁面滾動