iPad的Web应用程序:检测虚拟键盘在Safari中使用JavaScript?

我正在为iPad编写一个Web应用程序( 不是常规的App Store应用程序 – 它是使用HTML,CSS和JavaScript编写的)。 由于键盘填满了屏幕的一大部分,所以在显示键盘时改变应用的布局以适应剩余空间是有意义的。 但是,我发现没有办法检测键盘显示的时间或是否显示。

我的第一个想法是假设当文本字段有焦点时键盘是可见的。 但是,当外接键盘连接到iPad时,当文本字段获得焦点时,虚拟键盘不会显示。

在我的实验中,键盘也没有影响任何DOM元素的高度或滚动高度,并且我没有find专有的事件或属性来指示键盘是否可见。

我find了一个可行的解决scheme,虽然有点难看。 它也不会在任何情况下工作,但它对我有用。 由于我将用户界面的大小调整为iPad的窗口大小,用户通常无法滚动。 换句话说,如果我设置窗口的scrollTop,它将保持在0。

另一方面,如果显示键盘,则滚动突然起作用。 所以我可以设置scrollTop,立即testing它的值,然后重置它。 下面是使用jQuery在代码中看起来如何:

$(document).ready(function(){ $('input').bind('focus',function() { $(window).scrollTop(10); var keyboard_shown = $(window).scrollTop() > 0; $(window).scrollTop(0); $('#test').append(keyboard_shown?'keyboard ':'nokeyboard '); }); }); 

通常情况下,你会期望这不会被用户看到。 不幸的是,至less在模拟器中运行时,iPad显然(尽pipe很快)会再次上下滚动。 尽pipe如此,至less在某些特定的情况下是有效的。

我已经在iPad上testing过了,它似乎工作正常。

您可以使用focusout事件来检测键盘解除。 这就像模糊,但泡沫。 当键盘closures时(当然也包括其他情况),它会被触发。 在Safari和Chrome中,只能使用addEventListener注册事件,而不能使用传统方法注册。 这是我用来在解除键盘后恢复Phonegap应用程序的一个例子。

  document.addEventListener('focusout', function(e) {window.scrollTo(0, 0)}); 

没有这个片段,应用程序容器停留在向上滚动的位置,直到页面刷新。

也许稍微好一点的解决scheme是绑定(在我的情况下与jQuery)各种input字段上的“模糊”事件。

这是因为当键盘消失时,所有的表单都模糊不清。 所以对于我的情况这削减解决了这个问题。

 $('input, textarea').bind('blur', function(e) { // Keyboard disappeared window.scrollTo(0, 1); }); 

希望它有帮助。 米歇尔

如果有一个屏幕上的键盘,将焦点靠近视口底部的文本字段将导致Safari将文本字段滚动到视图中。 可能有一些方法可以利用这种现象来检测键盘的存在(在页面底部有一个微小的文本字段,暂时获得焦点,或类似的东西)。

在焦点事件期间,您可以滚动浏览文档的高度,神奇地浏览window.innerHeight减less虚拟键盘的高度。 请注意,虚拟键盘的大小与纵向和纵向不同,所以您需要在其更改时重新检测虚拟键盘的大小。 我build议不要记住这些值,因为用户可以随时连接/断开蓝牙键盘。

 var element = document.getElementById("element"); // the input field var focused = false; var virtualKeyboardHeight = function () { var sx = document.body.scrollLeft, sy = document.body.scrollTop; var naturalHeight = window.innerHeight; window.scrollTo(sx, document.body.scrollHeight); var keyboardHeight = naturalHeight - window.innerHeight; window.scrollTo(sx, sy); return keyboardHeight; }; element.onfocus = function () { focused = true; setTimeout(function() { element.value = "keyboardHeight = " + virtualKeyboardHeight() }, 1); // to allow for orientation scrolling }; window.onresize = function () { if (focused) { element.value = "keyboardHeight = " + virtualKeyboardHeight(); } }; element.onblur = function () { focused = false; }; 

请注意,当用户使用蓝牙键盘时,keyboardHeight是[上一个] [下一个]工具栏的高度。

当你做这个检测的时候有一点点的闪烁,但似乎不可能避免它。

编辑:由苹果公司logging,虽然我实际上无法得到它的工作:WKWebView 行为与键盘显示 :“在iOS 10中,WKWebView对象通过更新他们的window.innerHeight属性,当键盘显示,而不呼叫调整事件大小“(也许可以使用焦点或焦点加延迟检测键盘,而不是使用resize)。

编辑:代码假定屏幕键盘,而不是外部键盘。 离开它,因为信息可能对其他只关心屏幕键盘的人有用。 使用http://jsbin.com/AbimiQup/4查看页面参数。;

我们testingdocument.activeElement是否是一个显示键盘的元素(input type = text,textarea等)。 在iOS5,Chrome Mobile(Beta 2012年5月)和Android(ICS)和Opera(没有工作,因为Opera在键盘closures之后保持关注元素)的testing作品。

我认为它在某些情况下失败了(iOS注重input,转到主屏幕,然后回到页面?),但是对于我们所做的工作来说,它已经足够了。

下面的代码为我们的目的篡改事情(虽然通常不正确)。

 function getViewport() { // Note viewport sizing broken in Android 2.x see http://stackoverflow.com/questions/6601881/problem-with-meta-viewport-and-android var viewport = { left: window.pageXOffset, // http://www.quirksmode.org/mobile/tableViewport.html top: window.pageYOffset, width: window.innerWidth || documentElement.clientWidth, height: window.innerHeight || documentElement.clientHeight }; if (isTouchDevice && isInput(getActiveElement())) { // iOS *lies* about viewport size when keyboard is visible. See http://stackoverflow.com/questions/2593139/ipad-web-app-detect-virtual-keyboard-using-javascript-in-safari Input focus/blur can indicate, also scrollTop: return { left: viewport.left, top: viewport.top, width: viewport.width, height: viewport.height * (viewport.height > viewport.width ? 0.66 : 0.45) // Fudge factor to allow for keyboard on iPad }; } return viewport; } function isInput(el) { var tagName = el && el.tagName && el.tagName.toLowerCase(); return (tagName == 'input' && el.type != 'button' && el.type != 'radio' && el.type != 'checkbox') || (tagName == 'textarea'); }; function getActiveElement() { try { return document.activeElement; // can get exeption in IE8 } catch(e) { } }; 

上面的代码只是近似的:拆分键盘,脱开键盘,物理键盘是错误的。 根据顶部的注释,您可能能够比使用window.innerHeight属性的Safari(自iOS8?)或WKWebView(自iOS10以上)上的给定代码做得更好。

但是,标记的答案(改变的scrolltop测量高度)有令人讨厌的UI副作用,如果视口可缩放(或偏好启用强制缩放)。 我不使用其他build议的解决scheme(改变的scrolltop),因为在iOS上,当视口可缩放和滚动焦点input时,滚动和缩放焦点之间的交互作用(这可以在视口之外留下一个刚聚焦的input – 不可见)。

仅在Android 4.1.1上进行testing:

模糊事件不是一个可靠的事件来testing键盘的上下,因为用户作为选项来显式隐藏键盘,而不会在引起键盘显示的字段上触发模糊事件。

resize的事件,但如果键盘出于任何原因出现或closures,就像一个魅力。

咖啡:

 $(window).bind "resize", (event) -> alert "resize" 

任何时候因任何原因显示或隐藏键盘都会触发。

但是,在Android浏览器(而不是应用程序)的情况下请注意,有一个可伸缩的url栏,当它被收回时不会resize,但会改变可用的窗口大小。

尝试检测窗口的大小,而不是检测键盘

如果窗口高度减小,宽度仍然相同,则意味着键盘已打开。 否则键盘是closures的,您也可以添加到,testing是否有任何input字段在焦点上。

例如试试这个代码。

 var last_h = $(window).height(); // store the intial height. var last_w = $(window).width(); // store the intial width. var keyboard_is_on = false; $(window).resize(function () { if ($("input").is(":focus")) { keyboard_is_on = ((last_w == $(window).width()) && (last_h > $(window).height())); } }); 

这个解决scheme记住了滚动位置

  var currentscroll = 0; $('input').bind('focus',function() { currentscroll = $(window).scrollTop(); }); $('input').bind('blur',function() { if(currentscroll != $(window).scrollTop()){ $(window).scrollTop(currentscroll); } }); 

试试这个:

 var lastfoucsin; $('.txtclassname').click(function(e) { lastfoucsin=$(this); //the virtual keyboard appears automatically //Do your stuff; }); //to check ipad virtual keyboard appearance. //First check last focus class and close the virtual keyboard.In second click it closes the wrapper & lable $(".wrapperclass").click(function(e) { if(lastfoucsin.hasClass('txtclassname')) { lastfoucsin=$(this);//to avoid error return; } //Do your stuff $(this).css('display','none'); });`enter code here` 

我做了一些search,我找不到任何具体的“键盘显示”或“键盘解散”。 查看支持事件的官方列表 。 另请参阅iPad的技术说明TN2262 。 正如你可能已经知道的那样,你可以通过电线连接来检测风景/肖像。

同样,但一个疯狂的猜测…你有没有尝试检测resize? 视口变化可能会从显示/隐藏的键盘间接触发该事件。

 window.addEventListener('resize', function() { alert(window.innerHeight); }); 

这将只是提醒任何resize事件的新高度….

我还没有尝试过这个,所以它只是一个想法…但你有没有尝试过使用CSS的媒体查询,看看什么时候窗口的高度改变,然后改变devise呢? 我会想象,Safari移动不认识到键盘作为窗口的一部分,所以希望工作。

例:

 @media all and (height: 200px){ #content {height: 100px; overflow: hidden;} } 

问题在于,即使在2014年,软件键盘打开时,设备也会处理屏幕大小调整事件以及滚动事件。

我发现,即使你使用的是蓝牙键盘,iOS也会触发一些奇怪的布局错误; 所以我没有检测到软键盘,而只是瞄准非常窄的触摸屏设备。

我使用媒体查询(或window.matchMedia )进行宽度检测,使用Modernizr进行触摸事件检测。

正如在前面的答案中指出的那样,当键盘出现时, window.innerHeightvariables现在在iOS10上得到了正确的更新 ,由于我不需要对早期版本的支持,所以我想出了下面这个可能稍微简单一些的hack “解决scheme”。

 //keep track of the "expected" height var windowExpectedSize = window.innerHeight; //update expected height on orientation change window.addEventListener('orientationchange', function(){ //in case the virtual keyboard is open we close it first by removing focus from the input elements to get the proper "expected" size if (window.innerHeight != windowExpectedSize){ $("input").blur(); $("div[contentEditable]").blur(); //you might need to add more editables here or you can focus something else and blur it to be sure setTimeout(function(){ windowExpectedSize = window.innerHeight; },100); }else{ windowExpectedSize = window.innerHeight; } }); //and update the "expected" height on screen resize - funny thing is that this is still not triggered on iOS when the keyboard appears window.addEventListener('resize', function(){ $("input").blur(); //as before you can add more blurs here or focus-blur something windowExpectedSize = window.innerHeight; }); 

那么你可以使用:

 if (window.innerHeight != windowExpectedSize){ ... } 

检查键盘是否可见。 我一直在我的networking应用程序中使用它一段时间,它运作良好,但(如所有其他解决scheme),你可能会发现一个情况,因为“预期”的大小没有得到适当的更新或失败。

那么,你可以检测到你的input框有焦点,你知道键盘的高度。 也有CSS可用来获取屏幕的方向,所以我认为你可以破解它。

不过,你会想要处理物理键盘的情况。