iPad Web应用程序:在Safari中使用JavaScript检测虚拟键盘?
我正在为iPad编写一个web应用程序(不是一个普通的应用商店应用程序——它是使用HTML、CSS和JavaScript编写的)。由于键盘占据了屏幕的很大一部分,因此在显示键盘时改变应用程序的布局以适应剩余空间是有意义的。但是,我没有找到检测键盘何时显示或是否显示的方法 我的第一个想法是假设当文本字段有焦点时,键盘是可见的。但是,当外部键盘连接到iPad时,当文本字段接收到焦点时,虚拟键盘不会显示iPad Web应用程序:在Safari中使用JavaScript检测虚拟键盘?,javascript,iphone,ipad,safari,web-applications,Javascript,Iphone,Ipad,Safari,Web Applications,我正在为iPad编写一个web应用程序(不是一个普通的应用商店应用程序——它是使用HTML、CSS和JavaScript编写的)。由于键盘占据了屏幕的很大一部分,因此在显示键盘时改变应用程序的布局以适应剩余空间是有意义的。但是,我没有找到检测键盘何时显示或是否显示的方法 我的第一个想法是假设当文本字段有焦点时,键盘是可见的。但是,当外部键盘连接到iPad时,当文本字段接收到焦点时,虚拟键盘不会显示 在我的实验中,键盘也不会影响任何DOM元素的高度或滚动高度,我没有发现任何专有事件或属性指示键盘是
在我的实验中,键盘也不会影响任何DOM元素的高度或滚动高度,我没有发现任何专有事件或属性指示键盘是否可见。我自己也没有尝试过,所以这只是一个想法。。。但是,您是否尝试过使用CSS的媒体查询来查看窗口的高度何时发生变化,然后改变其设计?我可以想象,Safari mobile没有将键盘识别为窗口的一部分,因此这很有可能会起作用 例如:
@media all and (height: 200px){
#content {height: 100px; overflow: hidden;}
}
如果有屏幕键盘,聚焦视口底部附近的文本字段将导致Safari将文本字段滚动到视图中。可能有某种方法可以利用这种现象来检测键盘的存在(在页面底部有一个很小的文本字段,可以瞬间获得焦点,或者类似的东西)。嗯,您可以检测输入框何时具有焦点,并且您知道键盘的高度。还有CSS可以用来获取屏幕的方向,所以我认为你可以破解它
不过,您可能希望以某种方式处理物理键盘的情况 我做了一些搜索,但我找不到任何具体的“键盘上显示”或“键盘上取消”。看见另请参见iPad。您可能已经知道,有一个body事件
onorientationchange
可以连接起来检测横向/纵向
类似地,但是一个疯狂的猜测。。。你试过了吗?视口更改可能会从显示/隐藏的键盘间接触发该事件
window.addEventListener('resize', function() { alert(window.innerHeight); });
这只会在任何调整大小的事件中提醒新高度…我找到了一个可行的解决方案,尽管它有点难看。它也不会在任何情况下都起作用,但对我来说是有效的。由于我正在根据iPad的窗口大小调整用户界面的大小,用户通常无法滚动。换句话说,如果我设置窗口的scrollTop,它将保持在0 另一方面,如果显示键盘,滚动会突然起作用。所以我可以设置scrollTop,立即测试它的值,然后重置它。下面是使用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 ');
});
});
通常情况下,您希望用户看不到这一点。不幸的是,至少在模拟器中运行时,iPad会明显地(尽管很快)上下滚动。不过,至少在某些特定情况下,它仍然有效
我在iPad上对此进行了测试,似乎效果不错。也许更好的解决方案是(在我的例子中使用jQuery)在各种输入字段上绑定“blur”事件 这是因为当键盘消失时,所有表单字段都会模糊。 因此,就我的情况而言,这个剪断解决了问题
$('input, textarea').bind('blur', function(e) {
// Keyboard disappeared
window.scrollTo(0, 1);
});
希望能有帮助。
Michele编辑:由Apple记录,尽管我实际上无法使其工作:WKWebView:“在iOS 10中,WKWebView对象通过在显示键盘时更新其window.innerHeight属性来匹配Safari的本机行为,并且不调用调整大小事件”(也许可以使用焦点或焦点加延迟来检测键盘,而不是使用调整大小) 编辑:代码假定为屏幕键盘,而不是外部键盘。保留它是因为信息可能对只关心屏幕键盘的其他人有用。用于查看页面参数 我们测试
document.activeElement
是否是一个显示键盘的元素(输入类型=text、textarea等)
下面的代码是为了我们的目的而捏造的(尽管通常不正确)
上面的代码只是近似值:拆分键盘、未固定键盘、物理键盘是错误的。根据顶部的注释,使用window.innerHeight
property,您可能比Safari(自iOS8?)或WKWebView(自iOS10)上的给定代码做得更好
我在其他情况下也发现了失败:例如,将焦点放在输入上,然后转到主屏幕,然后返回页面;iPad不应该使视口变小;旧的IE浏览器无法工作,Opera无法工作,因为Opera在键盘关闭后仍将焦点放在元素上
但是,如果视口可缩放(或在首选项中启用强制缩放),则带标签的答案(更改scrolltop以测量高度)会产生恶劣的UI副作用。我不使用其他建议的解决方案(更改scrolltop)因为在iOS上,当视口可缩放并滚动到聚焦输入时,滚动、缩放和聚焦之间会出现错误交互(可能会将刚刚聚焦的输入留在视口之外-不可见)。仅在Android 4.1.1上测试: 模糊事件不是测试键盘上下的可靠事件,因为用户可以选择显式隐藏键盘,而不会触发导致键盘显示的字段上的模糊事件 但是,如果键盘出于任何原因上下移动,调整大小事件就像一个符咒 咖啡:
$(window).bind "resize", (event) -> alert "resize"
无论何时出于任何原因显示或隐藏键盘,都会激发
但是请注意,对于android浏览器(而不是应用程序),有一个可伸缩的url栏,当它被收缩时不会触发调整大小,但会更改可用的窗口大小。此解决方案会记住滚动位置
var currentscroll = 0;
$('input').bind('focus',function() {
currentscroll = $(window).scrollTop();
});
$('input').bind('blur',function() {
if(currentscroll != $(window).scrollTop()){
$(window).scrollTop(currentscroll);
}
});
在焦点事件期间,您可以滚动文档高度并神奇地减少window.innerHeight
var currentscroll = 0;
$('input').bind('focus',function() {
currentscroll = $(window).scrollTop();
});
$('input').bind('blur',function() {
if(currentscroll != $(window).scrollTop()){
$(window).scrollTop(currentscroll);
}
});
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;
};
document.addEventListener('focusout', function(e) {window.scrollTo(0, 0)});
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`
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()));
}
});
//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){ ... }
function viewportHandler() {
var viewport = event.target;
console.log('viewport.height', viewport.height)
}
window.visualViewport.addEventListener('scroll', viewportHandler);
window.visualViewport.addEventListener('resize', viewportHandler);