【小贴士】虚拟键盘与fixed带给移动端的痛!
前言
今天来公司的主要目的就是研究虚拟键盘与fixed的问题,期间因为同事问起闭包与事件委托(阻止冒泡)相关问题,便穿插了一篇别的:
【小贴士】工作中的”闭包“与事件委托的”阻止冒泡“,有兴趣的朋友可以去看看,因为首页只能放一篇,这个就略去了
现在回到主要研究点,首先在移动端我们点击文本框后会出现一个虚拟键盘, 虚拟键盘让页面可视区域得到了充分利用,但是也带来了一些问题
问题源头
移动端虚拟键盘出现的条件是:文本框(文本类)获得焦点
但是文本框获得焦点未必会弹出键盘!!!
收起虚拟键盘的条件是:文本框失焦
PS:总而言之,我们认为会出现或者消失虚拟键盘的时候都可能不工作
在移动设备上,如果文本框在上方,点击不会有什么问题:
在设备的最下面的话,就有所不同了,整个块会上移,以将input区域显示出来
这个时候几个棘手的问题就出现了:
① 虚拟键盘的出现对页面来说是不可知的,这句话的理解是:没有键盘出现事件,没有办法获取键盘高度
② 键盘是“贴”在了viewport上,表面上不会对dom产生“任何”影响,但是这个时候一些定位元素的表现却变得“怪异”
比如:


可以看到,无论淘宝或者新浪,这个问题都存在,现在比较普遍的解决方案都是:移动端不采用fixed属性
于是我们来看看是否有其它方案
iscroll是否能解决
其实这个方案在周四的时候我便测试过了,但是结果让人很遗憾

作为官方给出的例子,在虚拟键盘弹出来后,光标会乱跑,这个还可以接受,但是:
① 头部不见了
② 偶尔不能显示获得焦点的input
这两个问题就让人难以接受了,于是,我们需要找到其他方案
解决方案
其实这个问题如果真要较真的话,我觉得需要深入研究两个知识点:
① viewport的原理
② 虚拟键盘的原理
就我手里现有资源来说,两个知识点一个都不深入,所以只能先从应用层面解决问题
应用层面解决方案
我们想到这么一个场景,如果我们能监控到键盘的行为,如果能的话,我们便可以
① 键盘弹出时候将fixed元素设置为static
② 键盘消失时候将fixed元素设置为fixed
那么我们能吗???
虽然这个方案比较恶心,我们还真能......答案是监控dom变化!
监控键盘
监控的方式其实筛选下来也不过两种:
① 时钟setInterval不停监控
② 系统级别的监控,比如键盘出现时候通知window一个事件,但是很遗憾现在还没有这个事件,但是这个事件等于
input类元素获取焦点 == 弹出虚拟键盘
input类元素失去焦点 == 收起虚拟键盘
但是我们前面已经说过,上面的原则不一定可靠,所以该种方案也未必可靠了
基于系统监控这点,我们还可以监控resize事件或者scroll事件,但是经过我的测试,setInterval表现比较好
于是,我们简单写一段代码,可靠是否满足需求:
window.alert = function (msg) {
$('body').append('<div>' + msg + '</div>')
};
function fixedWatch(el) {
if(document.activeElement.nodeName == 'INPUT'){
el.css('position', 'static');
} else {
el.css('position', 'fixed');
}
}
setInterval(function () {
fixedWatch($('#headerview header'));
}, 500);
根据测试结果来说,是满足我们的需求的,这里的header不会出问题,但是footer由于没有处理仍然会错位

于是这个问题似乎被我们修复了,但是你可以接受吗???这个方案有一个致命的恶心点!
不停的监控dom变化,浪费资源
那么这个问题可优化么?
似乎是可优化的,但是依旧会带来很多问题,优化的入口与出口便是input标签的focus事件
至于其失焦相关的事件便不予关注了,因为可能由一个input跳到另一个input
setTimeout(function () {
$('#dl_app img').hide();
}, 100);
window.alert = function (msg) {
$('body').append('<div>' + msg + '</div>')
};
window.res = null;
var i = 0;
function fixedWatch(el) {
alert(i++);
if(document.activeElement.nodeName == 'INPUT'){
el.css('position', 'static');
} else {
el.css('position', 'fixed');
if(window.res ) { clearInterval(window.res ); window.res = null; }
}
}
$('input').focus(function () {
if(!window.res) {
fixedWatch($('#headerview header'));
window.res = setInterval(function () {
fixedWatch($('#headerview header'));
}, 500);
}
});
这样的话,貌似能让代码看上去舒服一点,但是其代价却是所有input类标签都会多一个获得焦点事件,依旧令人痛惜
结语
今天的学习暂时到此,对于虚拟键盘的出现其实可能还有其他的问题,举一个例子来说:
如果我们点击按钮时候会出一个toast在中间,但是虚拟键盘刚好遮住了toast提示信息怎么办呢?这个问题与上述问题其实是一致的
然后这个解决方案的可接受程度,以及其实际是否解决了问题又或者引起了其它问题就需要实际证明了
至于各位有什么好的解决方案,或者想法,可以讨论讨论哦!!!
好了,今天暂时到这里,我们下次继续,如果有可能我们会详细学习下viewport以及虚拟键盘相关
【小贴士】虚拟键盘与fixed带给移动端的痛!的更多相关文章
- ios的虚拟键盘与fixed移动端的bug
//$('#search')表单input;$('.search_out')浮动元素 var u = navigator.userAgent, app = navigator.appVersion;v ...
- 【转】air调用windows自带的虚拟键盘
原文:http://bbs.9ria.com/blog-73243-19560.html 最近在做一个东西,需要用到虚拟键盘.刚开始准备用as3开发一套,结果突然想起来windows有个自带的虚拟键盘 ...
- ios设备触发虚拟键盘输入后position:fixed 无效的一些简单另类的解决方法。
首先看一下我要解决的问题,第一张图是正常的情况下,第二张图是点击了输入框之后的情况,就是要解决此问题~! 百度了一下解决方法,好像有以下的一些方法: 1. iscroll 2. Jquery Mobi ...
- 在移动端H5开发中(关于安卓端position:fixed和position:absolute;和虚拟键盘冲突的问题,以及解决方案)
一.在开发移动端webapp时,我们经常会遇到这样的问题,当我们需要在页面底部固定一个logo或者说明时,往往会采用position:fixed进行固定定位或者absolute定位到最底部 这是一个很 ...
- 【小贴士】zepto find元素以及ios弹出键盘可能让你很头疼
前言 在此,我不得不说移动端的兼容问题很多,并且很令人头疼,这不,这个星期又有两个让我逮着了,一个是使用zepto过程中出现的问题,一个是ios虚拟键盘的问题 我这里做一次记录,以免以后忘了,同时希望 ...
- C#调用Windows(8/10)自带的虚拟键盘
以下是调用代码: private const Int32 WM_SYSCOMMAND = 274; private const UInt32 SC_CLOSE = 61536; [DllImport( ...
- H5 IOS 虚拟键盘不回落的问题
在 H5 页面中,会发现在高版本的 IOS 系统中(ios12以上)和微信版本6.7.x以上,都会发现 input 等输入框,输入内容之后发现虚拟键盘消失,但是页面出现大面积白框. 解决办法(最后加上 ...
- android性能小贴士 翻译
转自http://developer.android.com/training/articles/perf-tips.html 性能小贴士: 这篇文档主要一些微优化可以提升应用程序性能,但是这些改变不 ...
- 隐藏虚拟键盘,解决键盘挡住UITextField问题
再正式开始之前,先来介绍一下IOS的键盘类型: 一.键盘风格 UIKit框架支持8种风格键盘 ? 1 2 3 4 5 6 7 8 9 10 typedef enum { UIKeyboard ...
随机推荐
- 记一次上传文件到七牛云存储的经历(Plupload & UEditor)(.net)
七牛 配置ACCESS_KEY和SECRET_KEY Qiniu.Conf.Config.ACCESS_KEY = "ACCESS_KEY"; Qiniu.Conf.Config. ...
- 利用Dapper ORM搭建三层架构
利用Dapper关系对象映射器写的简单的三层架构.Dapper:StackOverFlow在使用的一个微型的ORM,框架整体效率较高,轻量级的ORM框架.网上有较多的扩展.此处只是简单的调用Dappe ...
- [Node.js] 使用TypeScript编写Node项目
原文地址:http://www.moye.me/2015/04/25/using_typescript/ 入 TypeScript 坑有一段时间了,由衷的看好,所以决定在自留地絮叨一番. 是什么 Ty ...
- Clank – 快速构建移动 APP 原型的 HTML/CSS 框架
Clank 是一个自由和开放源码的 HTML/CSS 框架,可以帮助你轻松创建本地手机或平板电脑应用程序的原型.它着重于提供一致的用户界面,不会刻意去模仿一个特定的 OS .该框架是基于组件的,这样我 ...
- 别用symbolicatecrash来解析crash Log了
今天突然发现了一个解析iOS crash log的好方法,忍不住来分享一下. 相信每个做iOS开发的TX都应该不会对symbolicatecrash陌生,我们第一次遇到真机上产生的崩溃日志时,在网上搜 ...
- Linux脚本,关闭服务器的所有tomcat并且重新启动
echo '开始查找tomcat进程' ID=`ps -fx | grep tomcat | awk '{print $1}'` echo $ID echo "开始结束tomcat进程&qu ...
- MySql操作时间
今天 select * from 表名 where to_days(时间字段名) = to_days(now()); 昨天 7天 DAY) <= date(时间字段名) 近30天 DAY) &l ...
- Windows下elasticsearch插入数据报错!
按照官方文档操作,但是windows下有些不同,它不认识单引号',因此如果这样操作,就会报错: C:\Users\neusoft>curl localhost:9200/b1/b2/1 -d { ...
- C# CSV文件读写
public class CSVFileHelper { /// <summary> /// 将DataTable中数据写入到CSV文件中 /// </summary> /// ...
- 使用archiver在nodejs下打包
archiver是一个在nodejs中能跨平台实现打包功能的模块,可以打zip和tar包,是一个比较好用的三方模块. 使用前先安装archiver模块. npm install archiver 建立 ...