虚拟键盘打开时防止100%主体高度滚动?

问题描述 投票:0回答:3

我有一个带有粘性页眉和页脚元素的聊天应用程序。当移动虚拟键盘打开时,我将文档的高度设置为

window.visualViewport.height
。例如。如果浏览器的高度为 1000px,虚拟键盘为 400px,则
window.visualViewport.height
为 600px,并且
<html>
<body>
都设置为 600px。页眉和页脚都会在 600 像素视口中正确显示。

但是,用户仍然可以将整个页面向上滚动 400 像素,这意味着他们会在底部看到 400 像素的空白区域。如何在仍然具有粘性页眉/页脚的同时防止出现此空白空间?

我尝试过:

  1. 检测滚动事件,但它们没有被触发
  2. 在 600px 视口下方的元素上使用 IntersectionObserver,但它永远不会触发
  3. 在页脚上使用
    position: fixed
    ,但滚动时不粘在底部
  4. 文档的滚动 Y 位置始终为 0
  5. 设置
    navigator.virtualKeyboard.overlaysContent
    没有任何作用

主要在 Android + Chrome 中测试,但在 iOS + Safari 中也出现同样的问题。

视频演示,最初的底部空白是键盘:https://i.imgur.com/OMSXAAt.mp4

编辑赏金: 我使用

window.visualViewport.addEventListener('scroll', ...)
找到了一个 hacky 解决方案。在滚动时,我会在页面顶部添加一些等于
window.visualViewport.offsetTop
的填充。但是,存在一些滞后,因此用户可以滚动一点,然后滚动处理程序就会运行。在 iOS Safari 上,延迟可能会超过 1 秒。有更好的解决办法吗?

javascript css web-applications sticky-footer intersection-observer
3个回答
0
投票

如果键盘出现时位置没问题,我建议使用 virtualkeyboard 事件并使父 div 在活动时隐藏滚动,并在它再次消失时使其可滚动:

代码片段:

if ("virtualKeyboard" in navigator) {
  navigator.virtualKeyboard.addEventListener("geometrychange", (event) => {
    const { x, y, width, height } = event.target.boundingRect;
    // Test if the keyboard is open, you will have to write this yourself
    // But just for an example:
    let keyboardOpen = height > 0;
    if (keyboardOpen) {
        // Make the parent element stop scrolling by making the overflow hidden
        document.getElementById("parent-div").style.overflow = "hidden";
    } else {
        // Make the parent element scrollable again
        document.getElementById("parent-div").style.overflow = "scroll";
    }

  });
}

只需确保将正确的 div ID 插入到文档查询中,并在其 HTML 标记中为该 div 提供一个 ID。

参考资料:

Mozzila 虚拟键盘 API

虚拟键盘API


0
投票

你在这里。多种技术的组合似乎是最有效的。

来源:软键盘打开时获取视口高度

JSBin代码:https://jsbin.com/nayigetido/1/edit?html,css,js,output

JSBin 输出:https://output.jsbin.com/nayigetido/1

HTML:

<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content">
</head>
<body>
<div id="chat">
  <div class="messages">Messages</div>
  <input type="text"/>
</div>
</body>

CSS:

#chat{
  height:100%;
  width:100%;
  display:flex;
  flex-direction:column;
  padding:3em;
  box-sizing:border-box;
}
.messages{
  height:100%;
  flex:1 1 auto;
}
input{
  width:100%;
}

html,body{
  margin:0;
  height:100%;
}

JS:

window.addEventListener('resize', () => {
  const chat = document.getElementById('chat');
  chat.style.height = window.visualViewport.height + 'px';
});

-1
投票

当您的聊天应用程序中使用粘性页眉和页脚元素打开移动虚拟键盘时,您似乎面临着防止显示空白空间的一些挑战。您发现使用

window.visualViewport.addEventListener('scroll', ...)
和一些填充的 hacky 解决方案是正确的,但可能需要一些改进来减少延迟。让我们探索一些潜在的解决方案:

  1. 使用事件监听器的组合: 您可以同时使用
    resize
    scroll
    事件侦听器来处理视口大小和滚动位置的更改。当虚拟键盘打开时,会触发
    resize
    事件,当用户开始滚动时,会触发
    scroll
    事件。
let prevVisualViewportHeight = window.visualViewport.height;

function handleResize() {
  const currentVisualViewportHeight = window.visualViewport.height;
  const offsetDiff = prevVisualViewportHeight - currentVisualViewportHeight;
  document.body.style.paddingBottom = `${offsetDiff}px`;
  prevVisualViewportHeight = currentVisualViewportHeight;
}

function handleScroll() {
  const currentVisualScrollTop = window.visualViewport.scrollTop;
  if (currentVisualScrollTop !== 0) {
    window.visualViewport.scroll(0, 0); // Reset scroll position to prevent further scrolling
  }
}

window.visualViewport.addEventListener('resize', handleResize);
window.visualViewport.addEventListener('scroll', handleScroll);
  1. 使用 CSS 处理键盘覆盖: 您可以使用 CSS 在键盘打开时自动调整布局,而不是仅仅依赖 JavaScript。
html, body {
  height: 100%;
  overflow: hidden;
}

body.keyboard-open {
  padding-bottom: env(safe-area-inset-bottom);
  overflow: auto;
}

使用此 CSS,您可以在虚拟键盘打开或关闭时向 body 元素添加或删除

keyboard-open
类。

function handleKeyboardOpen() {
  document.body.classList.add('keyboard-open');
}

function handleKeyboardClose() {
  document.body.classList.remove('keyboard-open');
}

// Add event listeners to detect keyboard open/close events
// You can use the methods that work best for your application.
  1. 利用
    focusout
    事件: 当虚拟键盘关闭时,会触发
    focusout
    事件。您可以使用此事件删除填充并重置滚动位置。
function handleFocusOut() {
  document.body.style.paddingBottom = '0';
  window.visualViewport.scroll(0, 0); // Reset scroll position
}

// Add event listener to detect focusout event
// You can use the methods that work best for your application.

请记住选择最适合您的特定用例和目标平台的方法组合。每种方法都有其优点和局限性,但这些方法的组合可以提供更强大的解决方案。此外,您可能需要在各种设备和浏览器上测试这些解决方案以确保兼容性。

© www.soinside.com 2019 - 2024. All rights reserved.