ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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

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

numerous hacks and viewport properties 可以让我们获得更多的屏幕空间,但没有一个比 minimal-ui 更有效(在 iOS 7.1 中引入)。

昨天有消息称 iOS 8 beta4 已从 Mobile Safari 中删除了 minimal-ui(请参阅 iOS 8 Release Notes 中的 Webkit 部分),这让我们感到疑惑:

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

据我们所知,iOS 7 no longer respondswindow.scrollTo hack,这表明我们必须忍受较小的屏幕空间,除非我们采用垂直布局或使用 mobile-web-app-capable

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

soft fullscreen 我的意思是不使用 mobile-web-app-capable 元标记。

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

minimal-ui 曾经是中间立场,默认情况下会隐藏菜单,但 keeping it accessible with a tap - 尽管 Apple 可能由于其他可访问性问题(例如用户不知道在哪里点击以激活菜单)而将其删除。

Q3。全屏体验值得麻烦吗?

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

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

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

请参阅 stackoverflow.com/questions/18793072/…,详细了解为什么最小用户界面对某些应用程序至关重要。
我在 iOS 7 上遇到了同样的问题,因为我们正在寻找一个带有滑动/滚动事件的 Web 应用程序,但是在 iOS8 Beta 4 上测试了 onScroll 事件并且......它们可以工作。 ios8-scroll-events.heroku.com 不确定这是否有帮助,但 .. 你可以做到这一点。
遇到了同样的麻烦。目前只有 javascript“修复”,因为下面的 calc() 函数是唯一的答案。如果您知道更好的决定,请保持此线程更新。此致。

C
Community

在 iOS 8 中,minimal-ui 视口属性是 no longer supported。但是,minimal-ui 本身并没有消失。用户可以通过“触摸向下”手势进入最小用户界面。

管理视图状态有几个前提条件和障碍,例如,要让最小用户界面工作,必须有足够的内容让用户能够滚动;为了使最小用户界面持续存在,窗口滚动必须在页面加载时和方向更改后偏移。但是,there is no way of calculating the dimensions of the minimal-ui 使用了 screen 变量,因此无法提前告知用户何时处于最小用户界面中。

这些观察结果是作为开发 Brim – view manager for iOS 8 的一部分进行研究的结果。最终实现的工作方式如下:

加载页面时,Brim 将创建一个跑步机元素。跑步机元素用于为用户提供滚动空间。跑步机元素的存在确保用户可以进入最小用户界面视图,并且如果用户重新加载页面或更改设备方向,它会继续存在。它对用户始终是不可见的。此元素具有 ID 边缘跑步机。在加载页面或更改方向后,Brim 正在使用 Scream 检测页面是否处于最小 ui 视图中(如果内容高度为大于视口高度)。当页面处于最小用户界面时,Brim 将禁用文档的滚动(它以一种不影响主元素内容的安全方式执行此操作)。禁用文档滚动可防止向上滚动时意外离开最小用户界面。根据最初的 iOS 7.1 规范,点击顶部栏会带回 chrome 的其余部分。

最终结果如下所示:

https://i.stack.imgur.com/mVciy.gif

为了记录,如果您更喜欢编写自己的实现,值得注意的是,您不能在 orientationchange 事件之后立即使用 Scream 来检测设备是否处于最小 UI,因为 window 维度确实在旋转动画结束之前不反映新方向。您必须将侦听器附加到 orientationchangeend 事件。

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


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

由于没有模仿 minimal-ui 的编程方式,我们提出了一种不同的解决方法,使用 calc() 和已知的 iOS 地址栏高度来发挥我们的优势:

以下演示页面 (also available on gist, more technical details there) 将提示用户滚动,然后触发软全屏(隐藏地址栏/菜单),其中标题和内容填充新视口。

<!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>

C
Community

告别minimal-ui(现在)

确实,minimal-ui 既有用又有害,我想现在的权衡取舍有另一个平衡点,有利于更新、更大的 iPhone。

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

简而言之,我最终阻止了任何形式的最小用户界面,所以至少我的屏幕高度总是相同的,你总是知道你的应用程序有多少实际空间。

在时间的帮助下,足够多的用户将拥有更多空间。

编辑

我是怎么做的

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

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

然后:

然后使用 js,我将#main 的高度设置为窗口的可用高度。这也有助于处理 iOS 和 Android 中发现的其他滚动错误。这也意味着您需要处理如何更新它,请注意;到达滚动边界时,我会阻止过度滚动。这个在我的代码中有点深,但我认为你也可以遵循这个答案的原则来获得基本功能。我认为它可能会闪烁一点,但会完成这项工作。

查看演示(在 iPhone 上)

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


禁用最小用户界面对我来说似乎很合理。请包含有关如何执行此操作的简短说明!
你是对的,我添加了一些操作方法。许多其他方法将起作用。
根据我的 iPhone 5,您的演示不适用于 iOS8。
谢谢你让我知道,它必须是一些更新,因为它曾经工作过。你在野生动物园吗?你到底是什么意思,它不起作用?
我想在手机上全屏显示。我假设 #main 包含您要显示的所有元素。我可以知道 .view 的用途是什么吗?
S
Stephen Garside

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

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 并单击底部的按钮时,出现了地址和工具栏。这是因为按钮离显示结束太近了。我想最好在移动模式下将它们移到其他地方。
R
Razor

这里的根本问题似乎是,如果内容等于或小于视口,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 到底是做什么的?
如果您指的是 scrollIntoViewIfNeeded,它是 scrollIntoView (developer.mozilla.org/en-US/docs/Web/API/Element.scrollIntoView) 的非标准派生。顾名思义,该方法将元素滚动到视图中。 true 参数表示将视图与元素的顶部对齐。这实际上应该阻止您滚动。但实施存在缺陷。
s
scooterlord

我想评论/部分回答/分享我的想法。我正在为即将到来的一个大型项目使用溢出-y:滚动技术。使用它有两个主要优点。

a) 您可以从屏幕底部使用带有操作按钮的抽屉;如果文档滚动并且底部栏消失,点击位于屏幕底部的按钮将首先使底部栏出现,然后可以点击。此外,这个东西的工作方式会导致在最底部有按钮的模式出现问题。

b) 当使用溢出的元素时,在发生重大 css 更改的情况下,唯一需要重新绘制的内容是可视屏幕中的内容。当使用 javascript 动态更改多个元素的 css 时,这给了我巨大的性能提升。例如,如果您有一个需要重绘的 20 个元素的列表,并且其中只有两个在溢出元素的屏幕上,则只有那些被重绘,而其余的在滚动时被重绘。没有它,所有 20 个元素都将被重新绘制。

..当然,这取决于项目以及您是否需要我提到的任何功能。 Google 使用溢出的 gmail 元素来使用我在 a) 中描述的功能。 Imo,即使考虑到旧款 iphone 的小高度(如您所说的 372 像素),这也是值得的。


c
codeHot

这是可能的,使用我在 (https://gist.github.com/bitinn/1700068a276fb29740a7) 的帮助下整理的以下示例,但在 iOS 11 上不太适用:

这是适用于 iOS 11.03 的修改后的代码,如果对您有用,请发表评论。

关键是为 BODY 添加一些大小,以便浏览器可以滚动,例如:height: calc(100% + 40px);

下面的完整示例和在您的浏览器中查看的链接(请测试!)

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CodeHots iOS WebApp Minimal UI via Scroll Test</title>

    <style>
        html, body {
            height: 100%;
        }
        html {
            background-color: red;
        }
        body {
            background-color: blue;
            /* important to allow page to scroll */
            height: calc(100% + 40px);
            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;

        function interceptTouchMove(){
            // and disable the touchmove features 
            window.addEventListener("touchmove", (event)=>{
                if (!event.target.classList.contains('scrollable')) {
                    // no more scrolling
                    event.preventDefault();
                }
            }, false); 
        }

        function scrollDetect(event){
            // wait for the result to settle
            if( timeout ) clearTimeout(timeout);

            timeout = setTimeout(function() {
                console.log( 'scrolled up detected..' );
                if (window.scrollY > 35) {
                    console.log( ' .. moved up enough to go into minimal UI mode. cover off and locking touchmove!');
                    // hide the fixed scroll-cover
                    var cover = document.querySelector('div.cover');
                    cover.style.display = 'none';

                    // push back down to designated start-point. (as it sometimes overscrolls (this is jQuery implementation I used))
                    window.scrollY = 40;

                    // and disable the touchmove features 
                    interceptTouchMove();

                    // turn off scroll checker
                    window.removeEventListener('scroll', scrollDetect );                
                }
            }, 200);            
        }

        // listen to scroll to know when in minimal-ui mode.
        window.addEventListener('scroll', scrollDetect, false );
    </script>
</head>
<body>

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

</body>

此处的完整示例链接:https://repos.codehot.tech/misc/ios-webapp-example2.html


g
ganar

可以让 Web 应用程序在 iOS 和 Android 中全屏运行,it is called a PWA 经过大量努力,这是解决此问题的唯一方法。

PWA 为开发提供了许多不容错过的有趣选项。我已经做了一对,看看这个Public and Private Tender Manual For Designers(西班牙语)。 And here is an English explanation from the CosmicJS site


i
iFeli

我还没有为 iOS 做过网页设计,但从我记得在 WWDC 会议和文档中看到的内容来看,Mobile Safari 中的搜索栏和整个操作系统的导航栏现在会自动调整大小和缩小以显示更多内容。

您可以在 iPhone 上的 Safari 中对此进行测试,并注意到,当您向下滚动以查看页面上的更多内容时,导航/搜索栏会自动隐藏。

最好保留地址栏/导航栏,而不是创建全屏体验。我认为苹果不会很快这样做。而且他们最多不会自动控制地址栏何时显示/隐藏。

当然,您正在失去屏幕空间,特别是在 iPhone 4 或 4S 上,但从 Beta 4 开始似乎没有替代品。


我知道iOS7+的这个特性,但是看我上面的解释:由于文档的高度与浏览器视口完全相同,移动浏览器不会隐藏地址栏/导航菜单,因为在文档级别没有滚动。
既然 Beta 4 已经删除了该功能,这可能是一个限制。 Apple 有可能并且很可能会自动控制地址栏并阻止开发人员访问它。
I haven't done web design for iOS - 如果您正在做网页设计,您可以为每个平台做这件事。因为网络在每个平台上。
@Sumit 我知道在网络上工作是通用的,但是每个浏览器及其底层框架都有特定的 CSS 属性。因此 Chrome 可能有一些 Safari 和 FireFox 无法使用的属性,反之亦然。