• 解决IOS safari在input focus弹出输入法时不支持position fixed的问题


    该文章为转载

    我们在做移动web应用的时候,常常习惯于使用position:fixed把一个input框作为提问或者搜索框固定在页面底部。但在IOS的safari和webview中,对position:fixed的支持不是很好(在IOS5之前甚至还不支持position:fixed)。我遇到的其中一个问题就是,在iOS6+环境下,input focus弹出输入法的时候,设置了position fixed的input框浮在页面上了,而不是吸附在软键盘上。效果如图(图片来源于网上):

    而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则无需考虑此兼容方法。

    <!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>
  • 相关阅读:
    mysql关于time时间戳相关使用
    CentOS7环境对MySQL5.7的卸载及手动安装(非yum方式)
    eldialog弹窗偶现遮罩层全部变黑
    基于QToolButton封装,解决Icon不能设置hover和press态的问题
    Linux常用错误too many open files
    一套十万级TPS的IM综合消息系统的架构实践与思考
    基于Netty,徒手撸IM(一):IM系统设计篇
    如何用好 vim 里面的宏
    Nginx 面试题 40
    Mobaxterm在边栏中编辑/删除宏Macros
  • 原文地址:https://www.cnblogs.com/ghelement/p/4787087.html
Copyright © 2020-2023  润新知