h5實現輸入框fixed定位在屏幕最底部兼容性

一、問題由來css

作h5 已經有很長一段時間了,如今作的工做h5比pc上的更多,曾經解決pc端IE各個版本的兼容性也是傷透腦筋,原覺得h5的會更好,卻不知,還有更頭疼的問題,當設計師要設計一個聊天窗口,把輸入框定位在最底部,這是再常見不過的問題了吧,舉例:html

上圖就是我最近作的一個功能,原覺得是很簡單的一個定位功能,可是沒想到牛逼的測試竟然用各類iphone,各類安卓,各類瀏覽器(qq瀏覽器、safari、opera等瀏覽器),各類輸入法(系統自帶、搜狗輸入法),測出來一大堆問題,最後通過千辛萬苦,終於作到了能大體兼容。linux

 二、初步解決android

1)、結構佈局於第一次解決瀏覽器

 1 //1部分css
 2 .header {
 3     width: 100%;
 4     height: 40px;  
 5 }
 6 //2部分
 7 .body {
 8    width: 100%;
 9    overflow: auto;
10 }
11 //3部分
12 .footer {
13     width: 100%;
14     height: 30px;position: fixed; bottom:0;left:0;right:0;
15 }
1 <div class="header" id="header">會話問診</div>
2 <div class="body" id="body"></div>
3 <div class="footer" id="footer">
4      <input type="text" id="input">
5 </div>
1 $('.body').css('height', $(window).height() - 39); 
2 $('#input').on('focus', function () {
3    setTimeout(function () {
4                  window.scrollTo(0, 1000000);
5     }, 200);
6  });

這種佈局方法就讓中間".body"中的內容在".body"中滾動,對整個html中的body產生了1px的滾動,此處滾動的目的是爲了執行"window.scrollTo(0, 1000000);",通過測試,若body沒有產生滾動,則這個方法是不會執行的。iphone

 

相信不少人都會以 以上的方法解決input在彈出鍵盤時候的問題,當鍵盤彈出來後,就讓滾動條一直往下面滾直到滾動到最下面,沒錯,這種措施以後能保證大部分的正常,可是在safari瀏覽器中就出現了問題,因爲safari瀏覽器下部有一塊佈局

圖中是safari瀏覽器自帶的一塊標籤,當使用以上滾動時,你會發現,他雖然是滾動上去了,可是也會出現一塊空白,沒錯,至關於給你的感受是滾動上去過多,那麼此時,也會被測試打回,是否是感受很傷心無助,(safari瀏覽器把下面那塊看成了body的東西,他本身實現了一塊,把咱們的html內容裝在了他本身實現的容器裏面)測試

2)、進一步解決優化

通過大量的比較與測試,我發現了一個問題,safari下面的自帶輸入法根本不用處理,鍵盤依然能夠正常彈出與收起。(ps:safari瀏覽器沒有特別的判斷,所以此處判斷過於複雜,若有更好的判斷,請留言,謝謝!此處之因此判斷safari瀏覽器並非判斷QQ瀏覽器,是由於測試了opera瀏覽器的展現等跟QQ瀏覽器同樣,所以此處就判斷safari瀏覽器)this

 1 $('input').on('focus', function () {  var agent = navigator.userAgent.toLowerCase();
 2   setTimeout(function () {
 3                 if (agent.indexOf('safari') != -1 && agent.indexOf('mqqbrowser') == -1
 4                     && agent.indexOf('coast') == -1 && agent.indexOf('android') == -1
 5                     && agent.indexOf('linux') == -1 && agent.indexOf('firefox') == -1) {//safari瀏覽器 6                 } else {//其餘瀏覽器
 7                     window.scrollTo(0, 1000000);
 8                 }
9             }, 200);
10 });

3)、再次優化與解決

通過以上幾步驟,原覺得天衣無縫的解決方案,能夠達到很好的兼容了,但是意外又發生了,測試們用了搜狗輸入法來作測試,問題又來了,蘋果手機自帶的輸入法的實現是把body擠上去,搜狗則是在獲得focus以後,直接彈出的一塊遮罩層,這就致使了問題,此時咱們的輸入框被擋在了輸入法以後,所以又增長了下面的判斷與處理,

 1 $('input').on('focus', function () {
 2 setTimeout(function () {
 3                 if (agent.indexOf('safari') != -1 && agent.indexOf('mqqbrowser') == -1
 4                     && agent.indexOf('coast') == -1 && agent.indexOf('android') == -1
 5                     && agent.indexOf('linux') == -1 && agent.indexOf('firefox') == -1) {//safari瀏覽器
 6                     if(scope.$txtWrap.offset().top-winobj.scrollTop() > document.body.offsetHeight/2) { //說明軟鍵盤遮蓋頁面
 7                         window.scrollTo(0, winobj.height() - 270);
 8                     }
 9                 } else {//其餘瀏覽器
10                     window.scrollTo(0, 1000000);
11                 }
12             }, 200);
13 });

三、解決

通過幾回測試,看似幾乎沒問題,最後又在iphone5上面的QQ瀏覽器中用搜狗輸入法又測試出了問題,它在第一次點擊當input獲取到第一次focus事件的時候,window執行了scrollTo方法,第二次,他再也不執行,不難發現,系統是覺得已經滾動到了下方,所以便再也不執行,那麼我又增長了一個事件

$('input').on('blur', function () {
  window.scrollTo(0, 0);
});

終於大功告成,基本上解決了如今廣泛瀏覽器中大部分搜狗和自帶輸入法對模擬fix的input定位問題。

總結最後解決js爲:

 1 $('input').on('focus', function () {
 2     var agent = navigator.userAgent.toLowerCase();
 3   setTimeout(function () {
 4                 if (agent.indexOf('safari') != -1 && agent.indexOf('mqqbrowser') == -1
 5                     && agent.indexOf('coast') == -1 && agent.indexOf('android') == -1
 6                     && agent.indexOf('linux') == -1 && agent.indexOf('firefox') == -1) {//safari瀏覽器
 7                     if(scope.$txtWrap.offset().top-winobj.scrollTop() > document.body.offsetHeight/2) { //說明軟鍵盤遮蓋頁面
 8                         window.scrollTo(0, winobj.height() - 270);
 9                     }
10                 } else {//其餘瀏覽器
11                     window.scrollTo(0, 1000000);
12                 }
13             }, 200);
14 });
15 
16 $('input').on('blur', function () {
17     var agent = navigator.userAgent.toLowerCase();
18      setTimeout(function () {
19                 if (!(agent.indexOf('safari') != -1 && agent.indexOf('mqqbrowser') == -1
20                     && agent.indexOf('coast') == -1 && agent.indexOf('android') == -1
21                     && agent.indexOf('linux') == -1 && agent.indexOf('firefox') == -1)) {//非safari瀏覽器
22                         window.scrollTo(0, 0);
23                 }
24             }, 0);
25 });

重中之重,必定要讓body產生滾動,否則以上方法依然沒法解決。

 

最近同事又測出了個人方案對某些手機的不兼容性,因此他給出了另外一個解決方案,經測試已經達到了幾乎全部手機的兼容,下面提供給你們:

inputFocus: function (e) {
            var winobj = $(window),
                scope = this,
                agent = navigator.userAgent.toLowerCase();
            setTimeout(function () {
                if (agent.indexOf('safari') != -1 && agent.indexOf('mqqbrowser') == -1
                    && agent.indexOf('coast') == -1 && agent.indexOf('android') == -1
                    && agent.indexOf('linux') == -1 && agent.indexOf('firefox') == -1) {//safra瀏覽器
                    window.scrollTo(0, 1000000);//先滾動到最底部,再用scrollY獲得當前的值,必須延遲 不然拿到的就是1000000
                    setTimeout(function(){
                        window.scrollTo(0, window.scrollY - 45);//45像素 全部瀏覽器都是這麼高
                    }, 50)
                } else {//其餘瀏覽器
                    window.scrollTo(0, 1000000);
                    // window.scrollTo(0, ++this.scrollNum);
                }
            }, 200);
        },

  

 

這是我解決這個問題的過程與實踐,若你們有更好的思路,或者發現我這個方式依然沒法解決某些問題,請在留言區提出,謝謝!

相關文章
相關標籤/搜索