web移动端Fixed在Input获取焦点时ios下产生的BUG及处理

1.现象

可以看到下面两张图,图1搜索框为fixed固定在顶部,滚动没有任何问题。

图2当光标进入搜索框时,ios自作聪明的把光标定位到中间,并且fixed属性被自动修改成了absolute。此时注意滚动页面的话,会发现原本fixed的搜索框跟着文档一起滚动了。

再仔细观察ios下的一些特点,ios为了让input垂直居中,甚至还滚动了滚动条,原本看不到的上半段产品的内容也漏出来了。

 

2. 参考别人的解决方法

在网上搜索过后,大部分都是转载的这一篇文章,甚至配图都是拿别人原来的:

http://efe.baidu.com/blog/mobile-fixed-layout/

这个解决方案,主要用到了一个div包裹了整个可以滚动的部分,然后不能滚动的部分就固定在底部,不失为一种不错的解决方案,可惜我的搜索框不是一直固定在顶部,页面滚动到下面的时候才出现搜索框置顶,页面回到最顶部时搜索框要消失,并且我需要监控window.onscroll,做自动翻页的ajax请求等等,最后这个方案就没法使用了。即使要使用的话修改量应该也很大。

 

在参考了下面这篇文章后,想到了新的思路:

http://www.cnblogs.com/yexiaochai/p/3561939.html

 

3. 新的思路

文章中提到,

我们想到这么一个场景,如果我们能监控到键盘的行为,如果能的话,我们便可以

① 键盘弹出时候将fixed元素设置为static(最后我设置成absolute)

② 键盘消失时候将fixed元素设置为fixed

3.1 错误的尝试

基于这个想法,进行一系列的测试,首先static的意思是回归文档,导致整个搜索框都找不到了,因为可能回到文档最底部去了。所以static不可用,那么absolute呢,只要设置成absolute然后设置合适的top就可以了。思路是,根据滚动条获取top,然后通过$(window).height()获取屏幕可见区域的高度,估计虚拟键盘大概是一半,那么就除以2,然后减去搜索框的高度,就获得了偏移量。

最后top=top-偏移量,即可

想法是不错的,实现起来效果如何呢。观察之前的图2,我们可以猜测ios移动了滚动条,始终为了保证input处于垂直居中的位置,所以哪怕我们给他设置了top-偏移量,最后ios还是又往上滚动了一下。真是又爱又恨啊,你这么聪明你为什么搞这么个BUG出来呢。

 

 

3.2 最后的解决方案

还是回到图2去进行测试,当ios通过滚动条将input居中后,ios就不会再继续监控那个input了,此时我们随便拖拉页面,input都不会再回到中间,基于这个想法,那么我们通过js延迟一会来重新设置scroll可不可以呢? 

 

带着这样的想法进行了一些测试,最后解决方案如下

1. 监控input的focus和blur事件,进入时设置搜索框为absolute;

2. 获取当前scroll的高度,设置给搜索框的top;

3. 设置延迟函数,重新滚动滚动条到当前的top;

4. 离开input时恢复原来的fixed布局。

 

测试iphone6s ios 9.x 没问题

android 随便找了一台同事的vivo测试 没问题

暂时就测了2台手机

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head >
    <title></title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Cache-Control" content="no-cache">
    <meta http-equiv="Expires" content="0">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0" />
    <meta name="viewport" content="initial-scale=1, width=device-width, maximum-scale=1, user-scalable=no" />
    <meta name="viewport" content="initial-scale=1.0,user-scalable=no,maximum-scale=1"
        media="(device-height: 568px)" />
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-touch-fullscreen" content="yes" />
    <meta name="full-screen" content="yes" />
    <meta name="apple-mobile-web-app-status-bar-style" content="black" />
    <meta name="format-detection" content="telephone=no" />
    <meta name="format-detection" content="address=no" />
    
   
<style>
#float-search{
    height:40px;
    background:red;
    position:fixed;
    top:0;
    width:100%;
     
}
#float-search input{
    height:36px;
    border:1px solid #ccc;
    width:100px
 
}
</style>  
</head>
 
<body>
    <div class="warp">
     <p>1</p>
     <p>2</p>
     <p>3</p>
     <p>4</p>
     <p>5</p>
     <p>6</p>
     <p>7</p>
     <p>8</p>
     <p>9</p>
     <p>10</p>
     <p>1</p>
     <p>2</p>
     <p>3</p>
     <p>4</p>
     <p>5</p>
     <p>6</p>
     <p>7</p>
     <p>8</p>
     <p>9</p>
     <p>10</p>
     <p>1</p>
     <p>2</p>
     <p>3</p>
     <p>4</p>
     <p>5</p>
     <p>6</p>
     <p>7</p>
     <p>8</p>
     <p>9</p>
     <p>10</p>
     <p>1</p>
     <p>2</p>
     <p>3</p>
     <p>4</p>
     <p>5</p>
     <p>6</p>
     <p>7</p>
     <p>8</p>
     <p>9</p>
     <p>10</p>
     <p>1</p>
     <p>2</p>
     <p>3</p>
     <p>4</p>
     <p>5</p>
     <p>6</p>
     <p>7</p>
     <p>8</p>
     <p>9</p>
     <p>10</p>
     <p>1</p>
     <p>2</p>
     <p>3</p>
     <p>4</p>
     <p>5</p>
     <p>6</p>
     <p>7</p>
     <p>8</p>
     <p>9</p>
     <p>10</p>
     <p>1</p>
     <p>2</p>
     <p>3</p>
     <p>4</p>
     <p>5</p>
     <p>6</p>
     <p>7</p>
     <p>8</p>
     <p>9</p>
     <p>10</p><p>1</p>
     <p>2</p>
     <p>3</p>
     <p>4</p>
     <p>5</p>
     <p>6</p>
     <p>7</p>
     <p>8</p>
     <p>9</p>
     <p>10</p>
     <p>1</p>
     <p>2</p>
     <p>3</p>
     <p>4</p>
     <p>5</p>
     <p>6</p>
     <p>7</p>
     <p>8</p>
     <p>9</p>
     <p>10</p>
     <p>1</p>
     <p>2</p>
     <p>3</p>
     <p>4</p>
     <p>5</p>
     <p>6</p>
     <p>7</p>
     <p>8</p>
     <p>9</p>
     <p>10</p>
     <p>1</p>
     <p>2</p>
     <p>3</p>
     <p>4</p>
     <p>5</p>
     <p>6</p>
     <p>7</p>
     <p>8</p>
     <p>9</p>
     <p>10</p>
     <p>1</p>
     <p>2</p>
     <p>3</p>
     <p>4</p>
     <p>5</p>
     <p>6</p>
     <p>7</p>
     <p>8</p>
     <p>9</p>
     <p>10</p>
      
    </div>
    <div id="float-search">
       <input type="text" id="Text1" name="q" x-webkit-speech="" placeholder="搜索商品" autocomplete="off"
                    value="">
    </div>
    <div id="debugmsg" style="position: fixed; top: 20%; right:100px;width: 100px; height: 100px;
        border: 1px solid red;">
    </div>
</body>
  <script src="http://cdn.bootcss.com/jquery/3.1.0/jquery.js"></script>
<script>
 
function printStyles(elem) {
    var dtop = $(document).scrollTop();
    var position = $("#"+elem).css("position");
    var top = $("#"+elem).css('top');
    var height = $(window).height();//整个窗口高
     height = height / 4;
    var html = 'top:' + dtop + "<br/>"
        + "bodyTop:" + document.body.scrollTop + "<br/>"
        + "position:" + position + "<br/>" + "top:" + top + "<br/>"
        + "height:" + height;
    return html;
}
 
 
    $().ready(function () {
        window.onscroll = function() {
 
        //测试代码
        $("#debugmsg").html(printStyles('float-search'));
        //end 测试代码
 
        $("#float-search input").focus(function() {
            var top = $(document).scrollTop();
            var height = $(window).height();//整个窗口高
            height = height / 4;
 
            $("#float-search").css("position", "absolute");
            $("#float-search").css("top",top);
            setTimeout(function() {
                $("html,body").animate({scrollTop:top},5);//1000是ms,也可以用slow代替
            },5);
            //测试代码
        $("#debugmsg").html(printStyles('float-search'));
        //end 测试代码
 
        }).blur(function() {
            $("#float-search").css("position", "fixed");
            $("#float-search").css("top","0");
 
 
            //测试代码
         $("#debugmsg").html(printStyles('float-search'));
        //end 测试代码
        });
 
        }
    });
 
 
  
 
 
</script>
</html>

  

 

posted @   JangoJing  阅读(1598)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
点击右上角即可分享
微信分享提示