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

标签 javascript html css mobile progressive-web-apps

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

Note I'm not sure we want to make on-screen-keyboard work particularly well or even at all with fullscreen API, since that's primarily intended for video and fullscreen games. It's a low priority to support "regular websites" that for some reason use fullscreen API.



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

所以,我的结论是规避该问题的唯一现实方法是包含一个内置的 HTML5 OSK,如果我想要它全屏的话。这很好,因为我已经在制作中了。由于它是一个终端模拟器(有点类似于 Android 的 Termux),它需要完整的 101 键盘支持。目前我使用 Hackers 键盘,效果很好,并将 PWA 的“显示”设置为“独立”(我不太确定它是否符合“即时应用程序”的条件,但它确实从 Chrome 或Android 浏览器……还是 Chrome)。

如果有一个 hack 可以让用户使用他们的原生 IME 并适本地调整视口(viewport)的大小,我很想听到它,我可以看到其他人也愿意,通过帖子。我将这张票保持打开状态,因此遇到相同问题的开发人员不要为不受支持的事情浪费时间和精力,并希望有人找到解决方法。就我自己而言,我将继续使用内置的 HTML5 OSK。

有兴趣的可以引用门票herehere .

之前:
我有一个网络应用程序,我已经使用“安装到主屏幕”一段时间了。它是一个专门的基于 Web 的终端,使用 xterm.js 作为客户端的基础。自从在全屏模式下移植到 PWA 以来,我一直在“独立”中使用它,直到最近。在移动设备上,屏幕空间对于这样的应用来说非常宝贵,所以全屏是理想的——如果我能清除以下障碍:
  • Android 上的 IME(软键盘)与应用程序重叠,而不是调整视口(viewport)的大小,使其无法在全屏模式下使用。
  • 当 IME 弹出时,导航栏图标与应用程序顶部重叠,这是不可取的,因为全屏的重点是要求终端中可能是一两行额外文本的一英寸的一小部分。

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

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

    想法,有人吗?

    或者,如果有一种方法可以计算出软键盘的高度差,我可以在我的脚本中针对焦点事件设置高度,但我不确定如何执行此操作,因为它已经有了一个处理程序调整 font-size/cols/rows 监听 resize 事件,这就是为什么它在这种特殊情况下工作正常。

    更多信息:

    它正确安装到应用程序抽屉中,提示安装,注册服务 worker 等。如果我在 list 中设置“display”:“standalone”,它会在 IME 弹出或隐藏时正确调整大小,但是在设置时不会调整大小“显示”:“全屏”。它有一个很好的包装,包含所有推荐的 PWA 花里胡哨。该应用程序包含在 iframe 中。只要 iframe 改变了 IME 的大小,其余的就会随之改变。

    我尝试了固定位置和绝对位置、高度 100% 和 100vh,并尝试在 body 上设置这些的各种组合。我原以为它也能正常工作。

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

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

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

    我认为元视口(viewport)标签不重要,但它就是这样。不应该有任何浏览器页面缩放。它是一个终端客户端,具有显式的 GUI 控件来更改字体大小和相应的行/列数以适应 iframe。无论如何,它在以 list 中设置的“全屏”以外的任何其他方式查看时都可以正常工作,无论是在浏览器 chrome 中,还是“添加到主页”(在移植到 PWA 之前)等。它只有在以下情况下才有重叠作为带有 display:'fullscreen' 的 PWA 安装到应用程序抽屉(但不是在 PWA 移植之前通过 js 设置全屏时)。
    <meta id=viewport name=viewport
      content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"
    >
    

    这是一个稍微修改过的全屏 list 副本:
    {
      "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>
    

    Escape 等特殊键需要发送“转义字符代码”,例如:
    <button onclick='socket.send("\x1b")'>ESC</button>
    

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

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

    如果用于基于 Web 的终端模拟器,某些键(如箭头键)将需要终端“转义码”。此代码取决于 TERM 类型。对于 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 获得对单击/触摸的关注,否则 native IME 将弹出并挡路。您可以执行此操作的一种方法是在“prevent.default”的输入上使用单击和 touchstart 处理程序。这对 xterm.js 很有用(我不记得隐藏输入的 id,但您可以使用开发工具找到它)。对于传统输入,您可能只是用透明 div 覆盖它。不过,您可能想要伪造一个光标,因为您将避免实际焦点,它不会出现。有一些关于如何做到这一点的好网站。不过,我只是在这里介绍了基础知识,主要用于 xterm.js 用例,无论如何它都显示了一个光标,您只需重新设置它的样式,使其成为实线而不是轮廓。

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

    其他选项是:只使用小而高的输入,本地输入法不能重叠它们,或者将它们嵌套在足够大的东西中,无论如何都可以向上滚动(可能很乱),或者只是不使用全屏 - 使用“显示”:“独立”代替。

    也许如果有足够多的开发人员发现他们的问题,供应商会修复它。所以如果你不喜欢这个问题,我建议你去上面链接中指出的错误报告,并在报告中表达你的问题。已经很老了,里面有几年前的帖子列表
    从前到现在。

    祝你好运!

    关于javascript - 渐进式 Web 应用软键盘和导航栏在全屏中重叠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48473821/

    相关文章:

    javascript - 在 Chrome 扩展程序中使用 connectNative() 连接到 native 主机应用程序时,导致 "Error connecting to native app"的原因是什么?

    javascript - 同步 2 个选择框

    html - 图片源srcset的object-fit解决方案

    css - 如何使用css flex使列具有相同的宽度

    css - 如何将居中的 div 置于居中的 div 下方?

    javascript - 如何在特定位置启动 CSS3 动画?

    javascript - 将 ionic 移动应用程序与 Django 结合使用进行表单处理的最佳方式

    html - 使用 CSS 定位 HTML 按钮

    javascript - jquery .each() 只做最后一个元素

    Javascript/JQuery 连续循环主体背景颜色