iOS 8 移除了“minimal-ui”视口属性,还有其他“软全屏”解决方案吗?

IT技术 javascript ios css responsive-design mobile-safari
2021-01-17 07:35:33

(这是一个多部分的问题,我会尽力总结场景。)

我们目前正在构建一个响应式网络应用程序(新闻阅读器),允许用户在标签内容之间滑动,以及在每个标签内容内垂直滚动。

解决此问题的常见方法是使用包装器div填充浏览器视口,设置overflowhiddenauto,然后在其中水平和/或垂直滚动​​。

这种方法很好,但有一个主要缺点:由于文档的高度与浏览器视口完全相同,因此移动浏览器不会隐藏地址栏/导航菜单

许多技巧和视口属性使我们能够获得更多的屏幕空间,但没有一个像minimal-ui(在 iOS 7.1 中引入的)那样有效

昨天有消息称 iOS 8 beta4 已从minimal-uiMobile Safari 中删除(请参阅iOS 8 发行说明中的Webkit 部分),这让我们感到疑惑:

一季度。是否仍然可以隐藏 Mobile Safari 上的地址栏?

据我们所知,iOS的7不再响应window.scrollTo破解,这意味着我们不得不忍受较小的屏幕空间,除非我们采取垂直布局或使用mobile-web-app-capable

Q2。是否还有可能拥有类似的软全屏体验?

通过软全屏我真的是不使用mobile-web-app-capablemeta标签。

我们的网络应用程序可访问,任何页面都可以使用本机浏览器菜单添加书签或共享。通过添加mobile-web-app-capable我们可以防止用户调用这样的菜单(当它被保存到主屏幕时),这会混淆和对抗用户。

minimal-ui曾经是中间地带,默认情况下隐藏菜单但可以通过点击访问它- 尽管 Apple 可能由于其他可访问性问题(例如用户不知道在哪里点击以激活菜单)将其删除。

Q3。全屏体验值得吗?

看起来全屏 API不会很快出现在 iOS 上,但即使是这样,我也看不到菜单将如何保持可访问性(Android 上的 Chrome 也是如此)。

在这种情况下,也许我们应该保持移动 safari 原样,并考虑视口高度(对于 iPhone 5+,它是 460 = 568 - 108,其中 108 包括操作系统栏、地址栏和导航菜单;对于 iPhone 4 或更旧,它是 372)。

很想听听一些替代方案(除了构建本机应用程序)。

6个回答

在 iOS 8 中不再支持minimum-ui 视口属性。但是,minimum-ui 本身并没有消失。用户可以通过“触摸向下拖动”手势进入最小用户界面。

管理视图状态有几个先决条件和障碍,例如,要使minimum-ui 起作用,必须有足够的内容使用户能够滚动;为了使minimum-ui 保持不变,窗口滚动必须在页面加载时和方向更改后偏移。但是,没有办法使用screen变量计算minimum-ui的尺寸,因此无法提前知道用户何时在minimum-ui中。

这些观察结果是作为为 iOS 8开发Brim 视图管理器的一部分的研究结果最终实现的工作方式如下:

当页面加载时,Brim 将创建一个跑步机元素。跑步机元素用于为用户提供滚动空间。跑步机元素的存在确保用户可以进入最小 ui 视图,并且如果用户重新加载页面或更改设备方向,它会继续存在。它始终对用户不可见。此元素具有 ID brim-treadmill

在加载页面或更改方向后,Brim 使用 Scream来检测页面是否在最小 ui 视图中(如果内容高度为大于视口高度)。

当页面在最小用户界面时,Brim 将禁用文档的滚动(它以不影响主元素内容的安全方式执行此操作)。禁用文档滚动可防止在向上滚动时意外离开最小用户界面。根据最初的 iOS 7.1 规范,点击顶部栏会带回其余的 chrome。

最终结果如下所示:

在 iOS 模拟器中的 Brim。

为了文档起见,如果您更喜欢编写自己的实现,值得注意的是,您不能使用Scream来检测设备是否在orientationchange事件之后直接处于minimum-ui 中,因为window尺寸不会反映新方向,直到旋转动画已结束。您必须为orientationchangeend事件附加一个侦听器

Screamorientationchangeend已作为该项目的一部分开发。

这真的是一个永无止境的故事。我是 HTML 游戏开发人员,iOS 7.1 中的 minimum-ui 工作得很好 - 这是让应用程序全屏运行并同时能够触摸屏幕底部的唯一方法。页面滑动的解决方案很好,但还不够好:(Apple,我们需要为游戏正确实现全屏 API,拜托。
2021-03-21 07:35:33
看起来很好!我可以在没有初始滚动的情况下强制最小用户界面吗?
2021-03-28 07:35:33
@Petr:我完全同意。当在 7.1 中宣布此修复程序时,我们迅速推出了一个新的结帐购买流程,将主要 CTA 固定在屏幕底部..这工作和转换得很好!感觉非常“原生”且无缝。我认为这是确切的问题。如果您考虑一下,让 Web 应用程序感觉原生并不符合 Apple 的最佳利益。这实际上是与他们的 App Store 垄断的直接利益冲突。这是,IMO,修复一个如此有意义的功能然后故意删除的唯一有效原因。#my2Cents :)
2021-03-28 07:35:33
@PetrUrban 我相信 Apple 更愿意您将您的游戏发布为 phonegap 应用程序,而不是允许您通过网络提供服务。他们最近决定允许 safari 使用广告拦截器巩固了这一想法。
2021-03-28 07:35:33
这比我原来的答案更广泛,标记为新答案,直到更好的解决方案出现:)
2021-03-29 07:35:33

由于没有模仿的编程方式minimal-ui,我们提出了不同的解决方法,使用calc()已知的 iOS 地址栏高度对我们有利:

下面的演示页面(也可以在 gist 上找到,那里有更多技术细节)将提示用户滚动,然后触发软全屏(隐藏地址栏/菜单),其中标题和内容填充新视口。

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Scroll Test</title>

    <style>
        html, body {
            height: 100%;
        }

        html {
            background-color: red;
        }

        body {
            background-color: blue;
            margin: 0;
        }

        div.header {
            width: 100%;
            height: 40px;
            background-color: green;
            overflow: hidden;
        }

        div.content {
            height: 100%;
            height: calc(100% - 40px);
            width: 100%;
            background-color: purple;
            overflow: hidden;
        }

        div.cover {
            position: absolute;
            top: 0;
            left: 0;
            z-index: 100;
            width: 100%;
            height: 100%;
            overflow: hidden;
            background-color: rgba(0, 0, 0, 0.5);
            color: #fff;
            display: none;
        }

        @media screen and (width: 320px) {
            html {
                height: calc(100% + 72px);
            }

            div.cover {
                display: block;
            }
        }
    </style>
    <script>
        var timeout;

        window.addEventListener('scroll', function(ev) {

            if (timeout) {
                clearTimeout(timeout);
            }

            timeout = setTimeout(function() {

                if (window.scrollY > 0) {
                    var cover = document.querySelector('div.cover');
                    cover.style.display = 'none';
                }

            }, 200);

        });
    </script>
</head>
<body>

    <div class="header">
        <p>header</p>
    </div>
    <div class="content">
        <p>content</p>
    </div>
    <div class="cover">
        <p>scroll to soft fullscreen</p>
    </div>

</body>
</html>

告别minimal-ui(暂时)

确实如此,minimal-ui可能有用也可能有害,我想权衡现在有了另一个平衡,有利于更新、更大的 iPhone。

在使用我的 HTML5 应用程序的 js 框架时,我一直在处理这个问题。在多次尝试解决方案后,每一个都有其缺点,我放弃了考虑 iPhone 6 之前的空间损失。鉴于这种情况,我认为唯一可靠且可预测的行为是预先确定的行为。

简而言之,我最终阻止了任何形式的 minimum-ui,因此至少我的屏幕高度始终相同,并且您始终知道应用程序的实际空间。

随着时间的推移,足够多的用户会有更多的空间。


编辑

我怎么做

为了演示目的,这有点简化,但应该适合您。假设你有一个主容器

html, body, #main {
  height: 100%;
  width: 100%;
  overflow: hidden;
}
.view {
  width: 100%;
  height: 100%;
  overflow: scroll;
}

然后:

  1. 然后使用 js,我将#main的高度设置为窗口的可用高度。这也有助于处理在 iOS 和 Android 中发现的其他滚动错误。这也意味着您需要处理如何更新它,只需注意;

  2. 当到达滚动的边界时,我会阻止过度滚动。这个在我的代码中更深一些,但我认为您也可以遵循此答案的基本功能原则我认为它可以稍微闪烁一下,但可以完成这项工作。


查看演示(在 iPhone 上)

作为旁注:这个应用程序也可以添加书签,因为它使用内部路由到散列地址,但我还添加了一个提示 iOS 用户添加到主页。我觉得这种方式有助于忠诚度和回头客(因此失去的空间又回来了)。

禁用最小用户界面对我来说似乎非常合理。请包括如何做到这一点的简短说明!
2021-03-17 07:35:33
感谢您让我知道,它必须是一些更新,因为它曾经可以工作。你在野生动物园吗?你到底是什么意思,它不起作用?
2021-03-25 07:35:33
根据我的 iPhone 5,您的演示不适用于 iOS8。
2021-04-08 07:35:33
你说得对,我添加了一些操作方法。许多其他方法将起作用。
2021-04-10 07:35:33

我发现解决这个问题的最简单的方法是将 body 和 html 元素的高度设置为 100.1%,用于用户代理是 iphone 的任何请求。这仅适用于横向模式,但这就是我所需要的。

html.iphone, 
html.iphone body { height: 100.1%; }

https://www.360jungle.com/virtual-tour/25查看

谢谢@斯蒂芬。身高:100.1% 帮助了我。但是,当我在 iPhone(iOS 11.1.1) Safari 上打开360jungle.com/virtual-tour/25并单击底部的按钮时,出现了地址和工具栏。这是因为按钮太靠近显示的末端。我想最好在移动模式下将它们移到其他地方。
2021-03-21 07:35:33

这里的根本问题似乎是,如果内容等于或小于视口,iOS8 safari 在向下滚动时不会隐藏地址栏。

正如您已经发现的,在底部添加一些填充可以解决这个问题:

html {
    /* enough space to scroll up to get fullscreen on iOS8 */
    padding-bottom: 80px;
}
// sort of emulate safari's "bounce back to top" scroll
window.addEventListener('scroll', function(ev) {
    // avoids scrolling when the focused element is e.g. an input
    if (
        !document.activeElement
        || document.activeElement === document.body
    ) {
        document.body.scrollIntoViewIfNeeded(true);
    }
});

上面的CSS应当有条件施用,例如与UA嗅探添加gt-ios8<html>

这个JS到底是做什么的?
2021-03-24 07:35:33
如果您指的是scrollIntoViewIfNeeded,则它是scrollIntoViewdeveloper.mozilla.org/en-US/docs/Web/API/Element.scrollIntoView)的非标准派生顾名思义,该方法将元素滚动到视图中。true参数表示将视图与元素的顶部对齐。这实际上应该会阻止您滚动。虽然实现是有缺陷的。
2021-04-06 07:35:33