简体   繁体   English

在 javascript 中检测屏幕上的虚拟键盘和横向

[英]Detect virtual keyboard on screen and landscape orientation in javascript

Am working on a html based mobile app where there is requirement to design app only for portrait orientation and display message to user when he goes to landscape, This feature is working fine with css media query but problem is this that I have a form in app and when I click on any of the textbox and virtual keyboard opens and screen height changes and it shows me message for orientation change我正在开发一个基于 html 的移动应用程序,该应用程序需要仅针对纵向设计应用程序并在用户进入横向时向用户显示消息,此功能适用于 css 媒体查询但问题是我在应用程序中有一个表单当我点击任何文本框时,虚拟键盘打开并且屏幕高度发生变化,它会显示方向变化的消息

Now I want to ask if there any way to different when actually orientation changes and when virtual keyboard on screen appears.现在我想问一下,当实际方向发生变化以及屏幕上出现虚拟键盘时,是否有任何不同的方法。 Thanks in advance提前致谢

@media screen and (orientation: landscape) {

}

I have checked other questions related to my topic on stackoverflow but nothing helpful there我已经检查了与我在 stackoverflow 上的主题相关的其他问题,但没有任何帮助

You can't detect whether there is or is not the virtual keyboard only using CSS. 您无法仅使用CSS检测虚拟键盘是否存在。 You'll need to use some javascript. 你需要使用一些JavaScript。

If you are using Cordova to build the app, try using the Keyboard plugin. 如果您使用Cordova构建应用程序,请尝试使用Keyboard插件。 It fires an event whenever keyboard is shown or hidden, so that you can respond to it somehow, ie. 它会在显示或隐藏键盘时触发事件,以便您可以以某种方式响应它,即。 add some class to <body> that will prevent showing the message. 将一些类添加到<body> ,这将阻止显示消息。

https://github.com/driftyco/ionic-plugin-keyboard https://github.com/driftyco/ionic-plugin-keyboard

Another approach would be to listen to "focus" event on all possible elements that can cause the keyboard to appear. 另一种方法是在可能导致键盘出现的所有可能元素上收听“焦点”事件。

$(document.body).on("focus", "textarea, input", function() {
   $(document.body).addClass("do-not-show-message");
}).on("blur", "textarea, input", function() {
   $(document.body).removeClass("do-not-show-message");
});;

The short answer: 简短的回答:

No, unfortunately there is no current way to detect when the virtual keyboard appears on screen. 不,遗憾的是,目前无法检测虚拟键盘何时出现在屏幕上。 Detecting orientation yes, that's possible using: 检测方向是,可以使用:

  1. css media queries ( as per you example ) css媒体查询( 根据你的例子
  2. via JavaScript using the orientationchange listener. 使用orientationchange侦听器通过JavaScript。
  3. via JavaScript using the resize listener and inferring the orientation using window.innerHeight > window.innerWidth 使用resize侦听器通过JavaScript并使用window.innerHeight > window.innerWidth推断方向

The long answer: 答案很长:

There should be no reason why the keyboard affects the orientation property that is interpreted by your css media query as follows: 应该没有理由键盘影响css媒体查询解释的orientation属性,如下所示:

@media screen and (orientation: landscape) {
    ...
}

The W3C media queries recomendation states the following for the orientation property: W3C 媒体查询推荐说明了以下的orientation属性:

The 'orientation' media feature is 'portrait' when the value of the 'height' media feature is greater than or equal to the value of the 'width' media feature. 当'height'媒体特征的值大于或等于'width'媒体特征的值时,'orientation'媒体特征是'portrait'。 Otherwise 'orientation' is 'landscape'. 否则'方向'是'风景'。

The keyboard being visible when you type in the forms textbox field simply should not trigger the orientation property to change. 键入表单文本框字段时键盘可见,不应触发orientation属性更改。

I have in the past had your issue occur when using device emulators, such as Device Mode in older versions of Google Chrome's devtools. 我在过去使用设备模拟器时遇到了问题,例如旧版Google Chrome的devtools中的设备模式。 However, when it was tested on real mobile device/s the issue did not occur. 但是,当它在真实的移动设备上进行测试时,问题没有发生。

Also, there is this bug open in mobile chrome that may be causing resize events to fire when the keyboard appears. 此外,在移动设备中打开此错误 ,可能会导致键盘出现时触发调整大小事件。

Perhaps the emulator, if that's what you are using, is incorrectly causing the the viewports height to change therefore causing the change to the orientation property in your media query. 也许模拟器,如果你正在使用它,会错误地导致视口高度发生变化,从而导致更改媒体查询中的orientation属性。

The simple gist I provided below does the following ( You could try running it in your dev environment to see what happens ): 我在下面提供的简单要点执行以下操作( 您可以尝试在开发环境中运行它以查看会发生什么 ):

  1. When the mobile device is in portrait orientation the screen shows two form input fields (displaying the words: 'foo' and 'baz'). 当移动设备处于纵向时,屏幕显示两个表单输入字段(显示单词:'foo'和'baz')。
  2. When I touch either of the form input fields the keyboard is displayed and there is no change to the content of the page. 当我触摸任何一个表单输入字段时,将显示键盘,并且页面内容没有变化。
  3. When the device it rotated 90 degrees to landscape orientation a gray panel appears showing the words: "Rotate your device to portrait" 当设备旋转90度到横向时,会出现一个灰色面板,显示“将设备旋转为纵向”字样

NOTE: The steps listed above are what happens when testing the gist below on several real mobile devices running Safari on iOS and mobile Chrome on Android (...not emulators!). 注意:上面列出的步骤是在iOS上运行Safari并在Android上运行移动Chrome的几个真实移动设备上测试下面的要点时发生的事情(...不是模拟器!)。

<!DOCTYPE html>

<html lang="en">

<head>
    <meta charset="utf-8" />
    <title>StackOveflow question 40175207</title>
    <meta name="description" content="Example gist using orientation css media query to hsow message when device is landscape" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
<style type="text/css">

body {
    padding: 0;
    margin: 0;
}

.wrapper {
    position: absolute;
    width: 100%;
    height: 100%;
    overflow: hidden;
    padding: 0;
    margin: 0;
}

.message-panel {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    background: gray;
    -webkit-transform: translateX(100%);
            transform: translateX(100%);

    will-change: transform;
}

.message-panel__text {
    position: absolute;
    top: 50%;
    text-align: center;
    font: 1em Helvetica, sans-serif;
    width: 100%;
    height: 50px;
    margin: auto;
    -webkit-transform: translateX(-50%);
            transform: translateY(-50%);
}

@media screen and (orientation: landscape) {
    .message-panel {
        transform: translateX(0);
    }
}

</style>

</head>
<body>
    <div class="wrapper">
        <form>
            <input type="text" name="input-one" value="foo">
            <input type="text" name="input-two" value="baz">
        </form>
        <div class="message-panel">
            <div class="message-panel__text">Rotate your device to portrait</div>
        </div>
    </div>
</body>
</html>

PS: There is also Web App Manifest in Chrome for Android which allows you to lock the orientation of the device too. PS:Chrome for Android中还有Web App Manifest,它允许您锁定设备的方向。 See here for further info. 有关详细信息,请参见此处

Hope this helps! 希望这可以帮助!

You can detect focus on input.您可以检测输入焦点。 It is very likely that the device will show a virtual keyboard in the mobile version of your application.设备很可能会在您的应用程序的移动版本中显示虚拟键盘。 To find out, you can compare the height of some element.要找出答案,您可以比较某些元素的高度。 For example, the application was 800 pixels high, nothing changed (there was no screen flip), but the height changed and now it is 500 pixels.例如,应用程序是 800 像素高,没有任何变化(没有屏幕翻转),但是高度改变了,现在是 500 像素。 And also you know that the focus is on the input field.而且您还知道焦点在输入字段上。 This may mean that a virtual keyboard has appeared on the screen.这可能意味着屏幕上出现了虚拟键盘。 Or not in some cases:)或者在某些情况下不是:)

I had troubles designing a chat view in HTML. 我在设计HTML中的聊天视图时遇到了麻烦。 Header at top, content center and chat field at the bottom. 顶部的标题,内容中心和底部的聊天字段。 In the end, this was the solution I opted for 最后,这是我选择的解决方案

  • Flexbox for the layout Flexbox用于布局
  • Height of the flexbox set to 100vh. flexbox的高度设置为100vh。
  • Because 100vh is problematic in Safari, detect Safari with js and set to 100% 因为在Safari中100vh是有问题的,所以用js检测Safari并设置为100%

Here's a fiddle that shows my solution 这是一个显示我的解决方案的小提琴

 var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); if (isSafari) { document.body.className = "is-safari"; } 
 html, body { padding: 0; margin: 0; } .chat { display: flex; flex-direction: column; justify-content: flex-start; align-items: stretch; align-content: stretch; width: 100%; height: 100vh; background: white; } .is-safari .chat { height: 100%; } .chat__header, .chat__footer { background: whitesmoke; height: 60px; } .chat__body { flex: 1; } 
 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>Chat View</title> </head> <body> <div class="chat"> <div class="chat__header">Header</div> <div class="chat__body">Body</div> <div class="chat__footer">Footer</div> </div> </body> </html> 

I used the following to detect the virtual keyboard being displayed.我使用以下内容来检测正在显示的虚拟键盘。 I assume 2 things:我假设两件事:

  1. The keyboard height is more than 50px, which helps ignore someone resizing a screen manually.键盘高度超过 50px,这有助于忽略手动调整屏幕大小的人。
  2. The width doesn't change when the keyboard is displayed.显示键盘时宽度不会改变。 This avoids catching someone rotating their screen.这样可以避免抓到有人旋转屏幕。

Basically, when the page loads, it saves the height and width.基本上,当页面加载时,它会保存高度和宽度。 You can do extra checks here to make sure the page isn't loaded in landscape.您可以在此处进行额外检查以确保页面未横向加载。 After that, any resize event runs a check.之后,任何调整大小事件都会运行检查。 Did the height go down by 50px or more, while the width stayed the same?高度 go 是否降低了 50px 或更多,而宽度保持不变? If so: keyboard was likely shown, If the height goes up by more than 50px while the width stays the same.如果是这样:可能显示键盘,如果高度增加超过 50px 而宽度保持不变。 the keyboard was hidden.键盘被隐藏了。

window.onload = WindowOnload;
window.onresize = WindowResize;

function WindowOnload() {
    document.body.setAttribute("height", window.innerHeight);
    document.body.setAttribute("width", window.innerWidth);
    if(window.innerHeight < window.innerWidth) { /* Page loaded in landscape */ }
}

function WindowResize() {
    const previousWidth = parseInt(document.body.getAttribute("width"));
    const newWidth = window.innerWidth;
    const previousHeight = parseInt(document.body.getAttribute("height"));
    const newHeight = window.innerHeight;

    if(previousWidth === newWidth) {
        if(previousHeight > newHeight+50) { /* Keyboard was displayed */ console.log("shown"); }
        else if (previousHeight+50 < newHeight) { /* Keyboard was hidden */ console.log("hidden"); }
    }

    document.body.setAttribute("height", window.innerHeight);
    document.body.setAttribute("width", window.innerWidth);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM