gpt4 book ai didi

javascript - 检测触摸屏设备上虚拟键盘的打开或关闭

转载 作者:行者123 更新时间:2023-11-28 03:52:43 41 4
gpt4 key购买 nike

对于这个问题,我有一个不太优雅的解决方法,我希望其他人可能已经有了更强大的解决方案。

<小时/>

在触摸屏上,点击可编辑文本字段将弹出屏幕键盘,这将更改可用的屏幕空间量。如果不加以处理,这可能会隐藏关键元素,或将页脚推到适当的位置。

在笔记本电脑或台式计算机上,打开可编辑文本字段不会造成此类布局更改。

在我当前的项目中,我希望确保即使虚拟键盘打开时某些关键项目也可见,因此我需要检测何时发生此类更改。然后,我可以向 body 元素添加一个类,以更改布局以适应键盘的存在。

在网上搜索现有的解决方案时,我发现:

  1. 没有完美的方法可以知道您的代码是否在移动设备上运行
  2. 有些非移动设备配有触摸屏,也可能配有键盘
  3. 焦点元素可能不可编辑
  4. contentEditable 元素将打开屏幕键盘
  5. 地址栏可能会在虚拟键盘出现的同时决定重新出现并占用必要的屏幕空间,从而进一步挤压可用空间。

我已在下面发布了我提出的解决方案。它依赖于检测键盘焦点变化后一秒内窗口高度的变化。我希望您能提出更好的解决方案,并经过跨平台、跨浏览器和跨设备的测试。

<小时/>

我创建了一个 repository on GitHub .
您可以测试我的解决方案here .

在我的测试中,如果用户使用带有触摸屏、键盘和鼠标的计算机,并且首先使用鼠标(取消)选择可编辑元素,然后立即更改窗口高度,则可能会出现误报。如果您在计算机或移动设备上发现其他误报或漏报,请告诉我。

<小时/>
;(function (){

class Keyboard {
constructor () {
this.screenWidth = screen.width // detect orientation
this.windowHeight = window.innerHeight // detect keyboard change
this.listeners = {
resize: []
, keyboardchange: []
, focuschange: []
}

this.isTouchScreen = 'ontouchstart' in document.documentElement

this.focusElement = null
this.changeFocusTime = new Date().getTime()
this.focusDelay = 1000 // at least 600 ms is required

let focuschange = this.focuschange.bind(this)
document.addEventListener("focus", focuschange, true)
document.addEventListener("blur", focuschange, true)

window.onresize = this.resizeWindow.bind(this)
}

focuschange(event) {
let target = event.target
let elementType = null
let checkType = false
let checkEnabled = false
let checkEditable = true

if (event.type === "focus") {
elementType = target.nodeName
this.focusElement = target

switch (elementType) {
case "INPUT":
checkType = true
case "TEXTAREA":
checkEditable = false
checkEnabled = true
break
}

if (checkType) {
let type = target.type
switch (type) {
case "color":
case "checkbox":
case "radio":
case "date":
case "file":
case "month":
case "time":
this.focusElement = null
checkEnabled = false
default:
elementType += "[type=" + type +"]"
}
}

if (checkEnabled) {
if (target.disabled) {
elementType += " (disabled)"
this.focusElement = null
}
}

if (checkEditable) {
if (!target.contentEditable) {
elementType = null
this.focusElement = null
}
}
} else {
this.focusElement = null
}

this.changeFocusTime = new Date().getTime()

this.listeners.focuschange.forEach(listener => {
listener(this.focusElement, elementType)
})
}

resizeWindow() {
let screenWidth = screen.width;
let windowHeight = window.innerHeight
let dimensions = {
width: innerWidth
, height: windowHeight
}
let orientation = (screenWidth > screen.height)
? "landscape"
: "portrait"

let focusAge = new Date().getTime() - this.changeFocusTime
let closed = !this.focusElement
&& (focusAge < this.focusDelay)
&& (this.windowHeight < windowHeight)
let opened = this.focusElement
&& (focusAge < this.focusDelay)
&& (this.windowHeight > windowHeight)

if ((this.screenWidth === screenWidth) && this.isTouchScreen) {
// No change of orientation

// opened or closed can only be true if height has changed.
//
// Edge case
// * Will give a false positive for keyboard change.
// * The user has a tablet computer with both screen and
// keyboard, and has just clicked into or out of an
// editable area, and also changed the window height in
// the appropriate direction, all with the mouse.

if (opened) {
this.keyboardchange("shown", dimensions)
} else if (closed) {
this.keyboardchange("hidden", dimensions)
} else {
// Assume this is a desktop touchscreen computer with
// resizable windows
this.resize(dimensions, orientation)
}

} else {
// Orientation has changed
this.resize(dimensions, orientation)
}

this.windowHeight = windowHeight
this.screenWidth = screenWidth
}

keyboardchange(change, dimensions) {
this.listeners.keyboardchange.forEach(listener => {
listener(change, dimensions)
})
}

resize(dimensions, orientation) {
this.listeners.resize.forEach(listener => {
listener(dimensions, orientation)
})
}

addEventListener(eventName, listener) {
// log("*addEventListener " + eventName)

let listeners = this.listeners[eventName] || []
if (listeners.indexOf(listener) < 0) {
listeners.push(listener)
}
}

removeEventListener(eventName, listener) {
let listeners = this.listeners[eventName] || []
let index = listeners.indexOf(listener)

if (index < 0) {
} else {
listeners.slice(index, 1)
}
}
}

window.keyboard = new Keyboard()

})()

最佳答案

有一个新的实验性 API,旨在准确跟踪由于键盘出现和其他类似的移动怪异而导致的尺寸变化。

window.visualViewport

https://developer.mozilla.org/en-US/docs/Web/API/Visual_Viewport_API

通过监听调整大小事件并将高度与所谓的“布局视口(viewport)”的高度进行比较。看到它发生了很大的变化,比如大约 30 像素。您可能会推断出类似“键盘正在显示”之类的信息。

if('visualViewport' in window) {
window.visualViewport.addEventListener('resize', function(event) {
if(event.target.height + 30 < document.scrollElement.clientHeight) {
console.log("keyboard up?");
} else {
console.log("keyboard down?");
}
});
}

(上面的代码未经测试,我怀疑缩放可能会触发误报,可能还需要检查缩放更改)

关于javascript - 检测触摸屏设备上虚拟键盘的打开或关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47841986/

41 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com