移動端ios升級到11及以上時,手機彈框輸入光標出現錯位問題


 

qa測試手機升級以后彈框輸入光標出現錯位現象,前兩天由於時間緊迫,一直沒有找到好的解決方案,今天一天都在解決這個bug問題,臨近下班終於算比較好的解決這個問題,覺得有必要理理~

引起原因:彈框的定位采取position:fixed,而ios(safari)對定位屬性position:fixed的解析不一致導致。

解決方案:

    方案一

       一開始上網找解決方案,找到如下處理方式。但存在當頁面出現滾動條時,彈框彈出后,頁面回滾至頂部。在不改變原有彈框代碼的情況下,有效地解決光標錯位問題,但嚴重影響用戶使用,只能忍痛舍去~

      
//彈框彈出后執行如下代碼
  $('body').css({'position': 'fixed', 'width': '100%'});
//彈框關閉后執行如下代碼
  $('body').css({'position': 'relative'});

  方案二

     嘗試多種方式后,只能從源頭解決,不使用position:fixed。重寫彈框定位,但問題是,這個彈框涉及所有頁面,后台開發用這彈框做了很多操作,彈框中間內容由於可以自定義,所以是牽一發而動全身,不敢輕易改,就連上傳圖片的進度條顯示都是用這個彈框做的(就是為了套用彈框的一個遮罩效果)

    解決思路:

     1.彈框(#pop )采用position:absolute定位,遮罩(#shadow)采用fixed定位(原先采用absolute定位的,由於有些頁面內容是根據用戶滾動進行動態加載,導致原先的遮罩不能完全遮住所有內容,當然也可以對某些元素定高進行加載內容,避免此類問題出現,但這次的修改要考慮通用性,后台開發有時候根本不管你這些,關鍵目前系統很多頁面都已經出現這問題了)

   2.彈框采用absolute定位后,關鍵是top值的確定(ios10.3 Safari 輸入鍵盤彈出時,若頁面底部被擠壓上去,則關閉彈框會復原到頁面滾動到底部時的狀態,若底部沒被擠壓上去,每彈出一次鍵盤,頁面都會上去一定距離,且不復原)

    var initTopH = function() {
        var tempH = $('#pop').height(); //彈框高度
        var screenH = $(window).height();//手機屏幕高度
        var scrollH = $(document).scrollTop();//文檔內容滾動高度
        var topH = scrollH + (screenH - tempH) / 2;//top值高度

             //解決當輸入鍵盤未手動關閉時,彈窗的定位問題
          if ($(document).height() - scrollH < screenH) {
               topH = $(document).height() - screenH + (screenH - tempH) / 2;
            }

        return topH;
    };

3.以為這樣就可以解決問題,但新的問題出現,當輸入框獲得焦點時,移動端會彈出鍵盤擠壓彈框上移,關閉鍵盤后,彈框不會恢復原位,所以需要對彈框失焦后在進行重新定位執行initTopH()

  $("#pop input,textarea").off('blur').on('blur', function() {
    //這里只是對input和textarea處理
            $('#pop').css({'top':initTopH()});
        });

4.  要成功解決一個問題,就會引發更多的問題需要解決,成功操作1-3的操作后,當彈框彈出后,若頁面存在滾動條,此時滾動頁面,彈框是不會跟着頁面下移的,因為top是寫死的。想當然是監聽頁面滾動(scroll)事件,實時改變top值,但問題是效果太差,抖動、彈跳太明顯,qa肯定會提bug的~

   另一途徑就是彈出彈框后禁止頁面滾動,以為設置body頁面overflow:hidden就好了,然而pc端模擬測試有效果,真實環境仍然不起作用。以為沒有給body定高,就都設置html,body標簽的高度為100%;但然並卵,反而出現  $(document).scrollTop() 取值有問題(用$('body').scrollTop()替換仍沒用,關鍵pc端模擬都有效果,一到真實環境就出問題),影響前面彈框定位。煩~煩~煩~,反復測試,都沒有實質性的進展~

     前面一直糾結於給body定高,但想想還是不妥,很多頁面開發者給各自頁面都會重新定義樣式,我這么暴力地修改,擔心影響其他頁面布局,所以果斷放棄這條路子~

    如何在不影響大局的情況下重新布局呢?突然想到了阻止默認事件  e.preventDefault() ,但是新問題又來了,使用這個可以很好的解決頁面滾動問題,但也會阻止彈框里內容滾動。糾結ing~

5.左思右想,采取整體除去局部的思想來監聽touchmove事件,方法如下,當觸摸對象不是彈框時,阻止默認事件,當觸摸對象是彈框時,雖然滾動彈框里的內容出現底部頁面也滾動的情況,但觸摸結束以后恢復原始的滾動高度,經測試效果還不錯,也不覺得突兀~

        $('#pop').show();
          var sh;//記錄初始滾動高度
            $(document).off('touchstart').on('touchstart', function(e) {
            sh = $(document).scrollTop();
        });
        $(document).off('touchmove').on('touchmove', function(e) {
            if (e.target.id === "shadow") {//除去#pop
                e.preventDefault();
            }
        });
        $(document).off('touchend').on('touchend', function(e) {
            $(document).scrollTop(sh);
        });

 

總結:雖然可能會有更好的解決方案,但這是我目前覺得比較好的處理方式,每個人所處的開發環境不一樣,考慮的東西也不同,所以此方法並不一定都適應,可以借鑒參考。一天都在解決這個bug問題,找資料,嘗試各種方法,雖然問題已解決,但還是想好好理順下思路,故寫下這篇隨筆~啦~啦~啦~啦,下班啦~

 

ps:領導說可以看下其他應用的彈框是否有此類問題,看下人家是怎么解決的,但我和小伙伴看了所有app,都沒找到類似彈出需要輸入文字的彈框(除iphone手機彈出用戶輸入id密碼外),大都是新開一個頁面讓用戶填寫,看來產品還是要往用戶習慣上靠~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM