渐进式 Web 应用程序软键盘和导航栏在全屏中重叠



>更新:好的。 所以,这看起来像另一个错误。 我在 chromium.org 找到了一些票证,说明基本上相同的问题。 在他们的情况下,他们将其显示为滚动问题,因为作为 Web 应用程序,它不会在输入焦点和 IME 弹出窗口上调整视口的大小,因此他们无法向下滚动到低于 IME 的输入字段,并且它不会自动向上滚动。 我的不使用普通输入字段(尽管 xterm.js实际上确实使用了一个,您只是从未看到它),但原因和结果是相同的:当 IME 弹出时视口不会调整大小,因此也不会触发调整大小事件。 票证摘录:

注意我不确定我们是否要使屏幕键盘特别工作 好吧,甚至根本没有全屏API,因为这主要是 适用于视频和全屏游戏。 这是一个低优先级 支持出于某种原因使用全屏 API 的"常规网站"。

根据工单中的工程师的说法,它被认为是一个极低的优先级,尽管从2015年到现在的帖子中有投诉。 显然没有计划解决上述问题,特别是因为Firefox具有相同的错误。

因此,我的结论是,规避这个问题的唯一现实方法是包含内置的HTML5 OSK,如果我希望它全屏显示的话。 这很好,因为我已经在工作中了。 由于它是一个终端模拟器(有点类似于Android的Termux),因此需要完整的101键盘支持。 目前,我使用黑客键盘,效果很好,并将PWA的"显示"设置为"独立"(我不太确定它是否符合"即时应用程序"的条件,但它确实从Chrome或Android浏览器创建并安装为apk..仍然是Chrome)。

如果有一个黑客,允许用户使用他们的本机 IME 并适当地调整视口的大小,我很想听听,我可以看到其他人也会通过帖子。 我将这张票保持打开状态,以便具有相同问题的开发人员不要将时间和精力浪费在不支持的事情上,并希望有人找到解决方法。 就我自己而言,如前所述,我将继续使用内置的HTML5 OSK。

对于那些感兴趣的人,您可以参考门票 这里 和 这里.


以前: 我有一个网络应用程序,我已经使用"安装到主屏幕"一段时间了。 它是一个专门的基于Web的终端,使用xterm.js作为客户端的基础。 直到最近,自从在全屏中移植到 PWA 中以来,我一直在"独立"中使用它。 在移动设备上,屏幕空间对于这样的应用程序来说是宝贵的,所以全屏是理想的 - 如果我能清除以下障碍:

  1. Android 上的 IME(软键盘)与应用重叠,而不是调整视口大小,使其无法在全屏模式下使用。

  2. 弹出 IME 时,导航栏图标与应用程序顶部重叠,这是不可取的,因为全屏的全部意义在于声明一英寸的分数,这可能是终端中的一两行额外文本。

我确信第一个有修复方法,但是我尝试过的任何事情都没有运气。 第二个,我不太确定。

我计划实现一个自定义的内部 IME——这将解决问题,但它只完成了一半,我希望用户仍然可以选择使用其设备上本机安装的 IME。

想法,有人吗?

或者,如果有一种方法可以计算出软键盘的高度差,我可以在焦点事件上设置脚本中的高度,但我不确定我将如何做到这一点,因为它已经有一个处理程序来调整字体大小/列/行侦听 resize 事件,这就是为什么它在这种特殊情况下工作正常。

更多信息:

它正确安装到应用程序抽屉中,提示安装,具有注册服务工作者等。 如果我在清单中设置"显示":"独立",它会在 IME 弹出或隐藏时正确调整大小,但是在设置"显示":"全屏"时不会调整大小。 它有一个很好的包装器,其中包含PWA的所有推荐花里胡哨的东西。该应用程序包装在 iframe 中。 只要 iframe 更改 IME 的大小,其余部分就会随之而来。

我尝试了固定和绝对位置,高度100%和100vh,并尝试在身体上设置各种组合。 我本来希望它只是工作一样。

不久前,在将其设置为PWA之前,我已经插入了一个功能以使其全屏显示,并且可以很好地调整IME的大小。 当时唯一的问题是导航栏中的图标与应用程序顶部重叠(如果我没记错的话,当 IME 隐藏时它们并没有消失,尽管它们现在作为 PWA 消失了)。

在这种情况下,独立版和全屏版之间唯一真正的区别是独立应用顶部停在导航栏上。 这是一个很小的差异,但很重要,因为在手机上的横向中,这是一整行或两行额外的行,具体取决于用户将字体设置为的大小(字体动态调整大小,以及调整大小事件时终端中的文本列/行数,并通过 +/- 图形控件)。

这是 iframe:

<iframe src=1ndex.html style="
position: fixed;  left: 0px;  top: 0px;  width: 100%;  height: 100%;  outline: none;  border: none;
"></iframe>

我认为元视口标签应该无关紧要,但它就在这里。 不应该有任何浏览器页面缩放。 它是一个终端客户端,具有显式 GUI 控件来更改字体大小和相应的行/列数以适应 iframe。 无论如何,当查看清单中设置的"全屏"以外的任何其他方式时,无论是在浏览器镶边中,"添加到主页"(在移植到 PWA 之前)等,它都应该工作。 它仅在作为带有显示的 PWA 安装到应用程序抽屉时具有重叠:"全屏"(但在 PWA 移植之前通过 js 全屏设置时不重叠)。

<meta id=viewport name=viewport
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"
>

下面是全屏清单的略微修改副本:

{
"name": "asdf",
"short_name": "asdf",
"description": "asdf,
"scope":"/asdf/",
"start_url": "https://asdf.com/asdf/index.html",
"display": "fullscreen",
"background_color": "#000",
"theme_color": "#000",
"icons": [{
"src": "/asdf/favicon.png",
"sizes": "192x192",
"type": "image/png"
}]
}

这是一个问题。 就 IME 存在时悬停在应用程序上的导航栏图标而言,除非修复程序相同,否则我什至不知道从哪里开始。 我所有的搜索词都是通常的教程页面,讨论如何设置PWA,或者带上它有多好。

我必须说,我对行为不同感到震惊,因为我认为它会默认为相同的行为。 仅仅因为应用是全屏的并不意味着你希望 IME 与应用的底部重叠。 无论如何,如果有解决方法,它可能非常简单,并不那么明显。

如上所述,这是一个公认的错误,没有修复计划。 如果你确实需要或希望你的应用在没有应用的 OSK/IME 覆盖部分的情况下获取软键盘输入,你可以通过一点 DIY OSK 来解决这个问题。 这真的很简单(嗯,大部分)。 如果你的用例和我一样,那就更容易了:你可以将字符直接发送到websocket。 假设您的 websocket 对象称为"socket",软键将如下所示:

<button onclick="socket.send(this.innerHTML)">A</button>

特殊键(如 Esc )需要发送"转义字符代码",如下所示:

<button onclick='socket.send("x1b")'>ESC</button>

--或\033,\u001b等,而不是\x1b。 所有功能等效。

请注意单引号和双引号的反转。 由于这在HTML5中是允许的,因此它比使用反斜杠来"转义"函数中的引号更容易。

某些键(如箭头键)需要终端"转义码",如果它适用于基于 Web 的终端模拟器。 此代码取决于术语类型。 对于 xterm,它通常是"\x1bO]A",或 B、C 或 D,具体取决于方向。 VT100 相同,但省略了 O。 您可能需要检查 termcap/terminfo db 或环境变量字符串以确保,具体取决于系统。

您可以通过复制小写或大写键盘(以您先制作的键盘为准)来模拟 Shift 或 Capslock,并将字母替换为它们的变体,本质上是一个单独的键盘。 将每个键盘包装在一个div 中,然后用"position: absolute; left: 0px; top: 0px;"样式,然后将两个键盘包装在另一个div 中。 将 onclick 处理程序附加到每个键盘上的 shift 键 - 在最上面的键盘上使用处理程序将其隐藏。 在底部键盘中,使用它再次显示顶部键盘。 实际上,这很像本机 IME 上的 shift 键。

如果目标是常规输入文本或文本区域,请使用以下模式:

document.getElementById('myinputelementid').value += 'A';

或密钥处理程序中的等效项。 您实际上应该首先永久"获取"输入,然后引用它而不是每次都获取它,但两者都可以工作。

对于传统的文本区域/输入,您必须以不同的方式处理箭头、胡萝卜(光标)放置和退格键。 我的用例是 xterm.js,它将通过终端转义序列处理实际的退格字符、箭头键等。 如果您需要使用常规输入,我让您查找这些操作的已建立 DOM 方法。 另一方面,您可以找到适合您需求的预制开源 OSK。 如果你使用 node.js,我在 npm 网站上看到过一个,虽然我不能肯定地说它做到了这一切,但我认为它确实做到了。 你可以通过谷歌搜索"npm osk"来找到它,或者直接在npm上搜索"osk"。

还有一件事,您需要阻止输入(包括 xterm.js获得对单击/触摸的关注,否则本机 IME 将弹出并妨碍。 您可以做到这一点的一种方法是在输入上使用单击和触摸启动处理程序来"prevent.default"。 这适用于 xterm.js(我不记得隐藏输入的 id,但您可以使用开发工具找到它)。 对于常规输入,您可能只是用透明的div 覆盖它。 不过,您可能想假装光标,因为您将避免实际焦点,它不会出现。 有一些关于如何做到这一点的好网站。 不过,我只是在这里介绍基础知识,主要是针对 xterm.js 用例,无论如何它都会显示光标,您只需重新设置它的样式,使其坚固而不是轮廓。

如果这在技术上没有涵盖整个解决方法,我深表歉意,但它确实涵盖了您需要的大部分内容,并让您知道该怎么做才能完成它,如果您选择走这条路。 我并不是说这一切都很容易。 但大部分都是。

其他选项是:仅使用足够小且足够高的输入,以使本机 IME 无法重叠它们,或者将它们嵌套在足够大的内容中,无论如何都可以向上滚动(可能很混乱),或者只是不使用全屏 - 改用"显示":"独立"。

也许如果有足够多的开发人员打扰他们,供应商会修复它。 因此,如果您不喜欢这个问题,我建议您转到上面链接中指示的错误报告,并在报告中表达您的问题。 它很旧,并且有一个来自几年的帖子列表 从前到现在。

祝你好运!

我使用 CSS 为我的渐进式 Web 应用程序解决了类似的解决方案。

使用键盘时,屏幕的高度要低得多,因此您可以使用CSS媒体查询来发挥自己的优势。例:

@media(max-height:520px) {
#bottom_menu {
display:none;
}
}

由于工单基本上标记为 WontFix,我将在此处链接我的通用黑客解决方法,发布在重复问题中:https://stackoverflow.com/a/73797159/6833854

最新更新