解決IOS safari在input focus彈出輸入法時不支持position fixed的問題

該文章爲轉載javascript

咱們在作移動web應用的時候,經常習慣於使用position:fixed把一個input框做爲提問或者搜索框固定在頁面底部。但在IOS的safari和webview中,對position:fixed的支持不是很好(在IOS5以前甚至還不支持position:fixed)。我遇到的其中一個問題就是,在iOS6+環境下,input focus彈出輸入法的時候,設置了position fixed的input框浮在頁面上了,而不是吸附在軟鍵盤上。效果如圖(圖片來源於網上):css

而Android則徹底沒這個問題,唉。那麼咱們只能針對IOS做兼容處理了。網上搜索了一通都沒能找到比較適合的解決方案(不打算用iScroll),無奈只得本身想辦法解決。琢磨良久後想到個折衷的辦法:用position:absolute以及經過js動態移動輸入框的位置來模擬position:fixed的效果,同時給window對象綁定一個滾動事件,讓input框往下移動的時候,能時刻緊貼着軟鍵盤。

因而問題來了,這個移動的位置應該是多少呢?

對圖片做像素級分析+debug得知,輸入框是被居中了。也就是說,輸入框到窗口頂部的距離等於它到軟鍵盤頂部的距離。不難算出,這個距離爲 $('input').offset().top - $(window).scrollTop()。因而後面的問題就迎刃而解了。須要說明的是,兼容後的效果確定比不上原生的position:fixed,但相比浮在頁面來講仍是要好很多吧。

基於zepto的主要代碼實現以下:
$('input').focus(function(){
        var _this = this;

        //無鍵盤時輸入框到瀏覽器窗口頂部距離
        var noInputViewHeight = $(window).height() - $(_this).height();

        //網頁正文內容高度
        var contentHeight = $(document).height() - $(_this).height();

        //控制正文內容高度大於一屏,保證輸入框固定底部
        contentHeight = contentHeight > noInputViewHeight ? contentHeight : noInputViewHeight;

        //由於彈出輸入法須要時間,需延時處理
        setTimeout(function(){

                //彈出輸入法時滾動條的起始滾動距離
                var startScrollY = $(window).scrollTop();

                //彈出輸入法時輸入框到窗口頂部的距離,即到軟鍵盤頂部的起始距離
                var inputTopHeight = $(_this).offset().top - startScrollY;

                //彈出輸入法時輸入框預期位置,即緊貼軟鍵盤時的位置。因輸入框此時處於居中狀態,因此其到窗口頂部距離即爲需往下移動的距離。
                var inputTopPos = $(_this).offset().top + inputTopHeight;

                //控制div不超出正文範圍
                inputTopPos = inputTopPos > contentHeight ? contentHeight : inputTopPos;

                //設置輸入框位置使其緊貼輸入框
                $(_this).css({'position':'absolute', 'top':inputTopPos });

                //給窗口對象綁定滾動事件,保證頁面滾動時div能吸附軟鍵盤
                $(window).bind('scroll', function(){

                        //表示此時有軟鍵盤存在,輸入框浮在頁面上了
                        if (inputTopHeight != noInputViewHeight) {

                                //頁面滑動後,輸入框需跟隨移動的距離
                                var offset = $(this).scrollTop() - startScrollY;

                                //輸入框移動後位置
                                afterScrollTopPos = inputTopPos + offset;

                                //設置輸入框位置使其緊貼輸入框
                                $(_this).css({'position':'absolute', 'top':afterScrollTopPos });
                        }
                });
        }, 100);
}).blur(function(){//輸入框失焦後還原初始狀態
        $(".div-input").removeAttr('style');
        $(window).unbind('scroll');
});

ps : 以上代碼在IOS6&7 safari中測試經過,IOS5及以前的版本沒作測試。Android由於完美支持position:fixed則無需考慮此兼容方法。html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<title>解決IOS safari在input focus彈出輸入法時不支持position fixed的問題</title>
<style type="text/css" rel="stylesheet">
input {position: fixed; bottom:2px; width: 90%; height:30px; font-size: 30px}
</style>
</head>

<body>

<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>

<input type="text" />

<script type="text/javascript" src="zepto.min.js"></script>
<script type="text/javascript">
//只做用於輸入框得到焦點時
$('input').focus(function(){
    var _this = this;
    //無鍵盤時輸入框到瀏覽器窗口頂部距離
    var noInputViewHeight = $(window).height() - $(_this).height();
    //網頁正文內容高度
    var contentHeight = $(document).height() - $(_this).height();
    //控制正文內容高度大於一屏,保證輸入框固定底部
    contentHeight = contentHeight > noInputViewHeight ? contentHeight : noInputViewHeight;
    //由於彈出輸入法須要時間,需延時處理
    setTimeout(function(){
        //彈出輸入法時滾動條的起始滾動距離
        var startScrollY = $(window).scrollTop();
        //彈出輸入法時輸入框到窗口頂部的距離,即到軟鍵盤頂部的起始距離
        var inputTopHeight = $(_this).offset().top - startScrollY;
        //彈出輸入法時輸入框預期位置,即緊貼軟鍵盤時的位置。因輸入框此時處於居中狀態,因此其到窗口頂部距離即爲需往下移動的距離。
        var inputTopPos = $(_this).offset().top + inputTopHeight;
        //控制div不超出正文範圍
        inputTopPos = inputTopPos > contentHeight ? contentHeight : inputTopPos;
        //設置輸入框位置使其緊貼輸入框
        $(_this).css({'position':'absolute', 'top':inputTopPos });
        //給窗口對象綁定滾動事件,保證頁面滾動時div能吸附軟鍵盤
        $(window).bind('scroll', function(){
            //表示此時有軟鍵盤存在,輸入框浮在頁面上了
            if (inputTopHeight != noInputViewHeight) {
                //頁面滑動後,輸入框需跟隨移動的距離
                var offset = $(this).scrollTop() - startScrollY;
                //輸入框移動後位置
                afterScrollTopPos = inputTopPos + offset;
                //設置輸入框位置使其緊貼輸入框
                $(_this).css({'position':'absolute', 'top':afterScrollTopPos });
            }
        });
    }, 100);
}).blur(function(){//輸入框失焦後還原初始狀態
    $(".div-input").removeAttr('style');
    $(window).unbind('scroll');
});
</script>

</body>
</html>
相關文章
相關標籤/搜索