Cordova 应用程序在 iPhone X 上显示不正确(模拟器)

我昨天用 Xcode 9.0(9A235)在 iPhone X Simulator 上测试了基于 Cordova 的应用程序,它看起来不太好。 首先,应用程序内容的上方和下方都有一个黑色区域,而不是填充整个屏幕区域。 更糟糕的是,在应用程序内容和黑色之间有两个白色条。

添加 cordova-plugin-wkwebview-engine以便使用 WKWebView (而不是 UIWebView)修复白色条形图的 Cordova 渲染。 由于使用 cordova-plugin-wkwebview-engine时的性能和内存泄漏问题,我的应用没有从 UIWebView 迁移到 WKWebView,当将从 Inapp 采购托管内容下载的图像加载到 HTML5画布时(由于 WKWebView 的安全限制,Webview 不能直接进行 file://访问,所以图像数据必须通过 cordova-plugin-file加载)。

这些截图显示了一个在 <body > 上设置了蓝色背景的测试应用程序。 在 UIWebView 的上方和下方,你可以看到白色的条形图,但是在 WKWebView 中看不到:


(来源: Pbrd.co)


(来源: Pbrd.co)

这两个 Cordova Webview 展示了黑色区域,相比之下,本地应用程序占据了整个屏幕区域:

115124 次浏览

我找到了解决白条 给你的办法:

在 viewport <meta>标签上设置 viewport-fit=cover,即:

<meta name="viewport" content="initial-scale=1, width=device-width, height=device-height, viewport-fit=cover">

然后,UIWebView 中的白条消失了:

移除黑色区域的解决方案(由 @ dpogue在下面的注释中提供)是使用 LaunchStoryboard 图像cordova-plugin-splashscreen来替换遗留的启动映像,Cordova 默认使用这些映像。为此,在 config.xml的 iOS 平台上添加以下内容:

<platform name="ios">
<splash src="res/screen/ios/Default@2x~iphone~anyany.png" />
<splash src="res/screen/ios/Default@2x~iphone~comany.png" />
<splash src="res/screen/ios/Default@2x~iphone~comcom.png" />
<splash src="res/screen/ios/Default@3x~iphone~anyany.png" />
<splash src="res/screen/ios/Default@3x~iphone~anycom.png" />
<splash src="res/screen/ios/Default@3x~iphone~comany.png" />
<splash src="res/screen/ios/Default@2x~ipad~anyany.png" />
<splash src="res/screen/ios/Default@2x~ipad~comany.png" />


<!-- more iOS config... -->
</platform>

然后在 res/screen/ios中创建具有以下尺寸的图像(删除任何现有尺寸) :

Default@2x~iphone~anyany.png - 1334x1334
Default@2x~iphone~comany.png - 750x1334
Default@2x~iphone~comcom.png - 1334x750
Default@3x~iphone~anyany.png - 2208x2208
Default@3x~iphone~anycom.png - 2208x1242
Default@3x~iphone~comany.png - 1242x2208
Default@2x~ipad~anyany.png - 2732x2732
Default@2x~ipad~comany.png - 1278x2732

一旦黑条被移除,iPhone X 还有另一个不同的地址: 由于“切口”,状态栏大于20px,这意味着你的 Cordova 应用程序最顶端的任何内容都会被它遮蔽:

与硬编码像素填充不同,您可以使用 iOS11中新的 safe-area-inset-*常量在 CSS 中自动处理这个问题。

注意: 在 iOS 11.0中,处理这些常量的函数被称为 constant(),但在 iOS 11.2中,苹果将其重命名为 env()(看这里) , 因此,为了同时覆盖这两种情况,您需要同时使用这两种 CSS 规则,并依赖于 CSS 回退机制来应用适当的 CSS 规则:

body{
padding-top: constant(safe-area-inset-top);
padding-top: env(safe-area-inset-top);
}

结果如我们所愿: 应用程序的内容覆盖了整个屏幕,但没有被“切口”遮挡:

我已经创建了一个 Cordova 测试项目,它演示了上面的步骤: Webview-test. zip

备注:

鞋底扣子

  • 如果你的应用程序有页脚按钮(和我的一样) ,你还需要应用 safe-area-inset-bottom来避免它们被 iPhone X 上的虚拟 Home 按钮重叠。
  • 在我的例子中,我不能将它应用到 <body>,因为页脚绝对位置正确,所以我需要将它直接应用到页脚:

.toolbar-footer{
margin-bottom: constant(safe-area-inset-bottom);
margin-bottom: env(safe-area-inset-bottom);
}

科尔多瓦-插件-状态栏

  • IPhone X 上的状态栏大小已经改变,所以旧版本的 cordova-plugin-statusbar在 iPhone X 上显示不正确
  • Mike Hartington 已经创建了应用必要更改的 这个请求
  • 这个版本已经合并到 cordova-plugin-statusbar@2.3.0版本中了,所以请确保您至少使用了这个版本来应用到安全区域插入

挡板

  • LaunchScreen 故事板约束在 iOS 11/iPhone X 上发生了变化,这意味着当使用现有版本的插件(看这里)时,样板在启动时会“跳转”。
  • 这是捕获在错误报告 CB-13505,固定公关 Cordova-ios # 354和发布在 cordova-ios@4.5.4,所以请确保您使用的是最新版本的 cordova-ios平台。

器件定位装置定位装置定位装置

  • 在 iOS11.0上使用 UIWebView 时,从纵向 > 横向 > 纵向旋转会导致 safe-area-inset无法重新应用,从而导致内容再次被缺口遮挡(正如下面的评论中 JMS所强调的那样)。
  • 也发生如果应用程序是在横向启动,然后旋转到肖像
  • 通过 cordova-plugin-wkwebview-engine使用 WKWebView 时不会发生这种情况。
  • 雷达报告: http://www.openradar.me/radar?id=5035192880201728
  • 更新 : iOS 11.1似乎已经修复了这个问题

作为参考,这是我打开的最初的 Cordova 问题,它捕获了这个: https://issues.apache.org/jira/browse/CB-13273

用于手动修复现有的 Cordova 项目

黑条

把它添加到 Info.plist文件中

<key>UILaunchStoryboardName</key>
<string>CDVLaunchScreen</string>

白条

在 meta 标记中设置 viewport-fit = cover

<meta name="viewport" content="initial-scale=1, width=device-width, height=device-height, viewport-fit=cover">

请注意,用于安全区域边距的 constant关键字已更新为11.2 beta + 版本的 env

Https://webkit.org/blog/7929/designing-websites-for-iphone-x/

如果在全球范围内安装较新版本的 ionic,则可以运行 它将为你生成所有的启动画面图像以及正确的大小。

你需要做三个步骤

IOs11状态栏和 iPhone X 头部问题


1. 视口配合盖

viewport-fit=cover添加到 <header>中的 viewport 元数据中

<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0,viewport-fit=cover">

演示: https://jsfiddle.net/gq5pt509(index.html)


  1. <platform name="ios">config.xml中添加更多的醒目图片

不要跳过这个步骤 ,这是获得 屏幕合适进行 IPhone X工作所必需的

<splash src="your_path/Default@2x~ipad~anyany.png" />   <!-- 2732x2732 -->
<splash src="your_path/Default@2x~ipad~comany.png" />   <!-- 1278x2732 -->
<splash src="your_path/Default@2x~iphone~anyany.png" /> <!-- 1334x1334 -->
<splash src="your_path/Default@2x~iphone~comany.png" /> <!-- 750x1334  -->
<splash src="your_path/Default@2x~iphone~comcom.png" /> <!-- 1334x750  -->
<splash src="your_path/Default@3x~iphone~anyany.png" /> <!-- 2208x2208 -->
<splash src="your_path/Default@3x~iphone~anycom.png" /> <!-- 2208x1242 -->
<splash src="your_path/Default@3x~iphone~comany.png" /> <!-- 1242x2208 -->

演示: https://jsfiddle.net/mmy885q4(config.xml)


  1. 在 CSS 上修正您的样式

使用 safe-area-inset-leftsafe-area-inset-rightsafe-area-inset-topsafe-area-inset-bottom

示例: (在您的案例中使用!)

#header {
position: fixed;
top: 1.25rem; // iOs 10 or lower
top: constant(safe-area-inset-top); // iOs 11
top: env(safe-area-inset-top); // iOs 11+ (feature)


// or use calc()
top: calc(constant(safe-area-inset-top) + 1rem);
top: env(constant(safe-area-inset-top) + 1rem);
  

// or SCSS calc()
$nav-height: 1.25rem;
top: calc(constant(safe-area-inset-top) + #{$nav-height});
top: calc(env(safe-area-inset-top) + #{$nav-height});
}

奖励: 你可以在 < a href = “ https://cordova.apache.org/docs/en/update/cordova/events/events. html”rel = “ noReferrer”> devicereready 上添加主体类,如 is-androidis-ios

var platformId = window.cordova.platformId;
if (platformId) {
document.body.classList.add('is-' + platformId);
}

所以你可以在 CSS 上做类似的事情

.is-ios #header {
// Properties
}

在我的例子中,每个启动画面都是单独设计的,而不是自动生成或以故事板格式布局的,我必须坚持我的 Legacy Launch 屏幕配置,并添加肖像和横向图像,以针对 iPhone X 1125 × 2436方向到 config.xml,如下所示:

<splash height="2436" src="resources/ios/splash/Default-2436h.png" width="1125" />
<splash height="1125" src="resources/ios/splash/Default-Landscape-2436h.png" width="2436" />

在将这些添加到 config.xml (“ viewport-fit = cover”已经在 index.hml 中设置)之后,我用 Ionic Pro 构建的应用程序填充了 iPhone X 设备上的整个屏幕。

修复 iPhone X/XS 屏幕旋转问题

在 iPhone X/XS 上,屏幕旋转将导致标题栏高度使用不正确的值,因为 safe-area-inset-* 的计算没有及时反映 UI 刷新时的新值。这个 bug 甚至在最新的 iOS12中也存在于 UIWebView 中。一个变通方法是插入一个1px 的顶部边距,然后迅速反转它,这将触发安全区域插入 * 立即重新计算。一个有点丑陋的修复,但它工作,如果你不得不留在 UIWebView 的原因或其他。

window.addEventListener("orientationchange", function() {
var originalMarginTop = document.body.style.marginTop;
document.body.style.marginTop = "1px";
setTimeout(function () {
document.body.style.marginTop = originalMarginTop;
}, 100);
}, false);

这段代码的目的是使 document.body. style.markTop 稍微发生变化,然后进行反转。它不一定是“1px”。您可以选择一个不会导致 UI 闪烁但达到其目的的值。

我开发科尔多瓦应用程序2年,我花了几个星期来解决相关的问题(例如: 当键盘打开时,webview 卷轴)。这里有一个经过测试和验证的解决方案,既适用于 ios 系统,也适用于 Android 系统

附注: 我使用 iScroll 滚动内容

  1. 永远不要在 index.html 的 meta 标签中使用 视窗适合 = 覆盖,让应用程序远离状态栏。IOS 将处理所有 iPhone 变体的适当区域。
  2. 在 XCode 中取消选中 隐藏状态栏需要全屏,并且不要忘记选择启动屏幕文件作为 启动屏幕
  3. 在 config.xml 中,将 全屏设置为 假的
  4. 最后,(感谢 Eddy Verbruggen 的伟大插件)添加他的插件 Cordova-plugin-webviewcolor来设置状态栏和底部区域的背景颜色。这个插件可以让你设置任何颜色你想要的。
  5. 将下面的代码添加到 config.xml (x 之后的第一个 ff 是不透明的)

    <preference name="BackgroundColor" value="0xff088c90" />
    
  6. Handle your scroll position yourself by adding focus events to input elements

    iscrollObj.scrollToElement(elm, transitionduration ... etc)
    

For android, do the same but instead of cordova-plugin-webviewcolor, install cordova-plugin-statusbar and cordova-plugin-navigationbar-color

Here's a javascript code using those plugins to work on both ios and android:

function setStatusColor(colorCode) {
//colorCode is smtg like '#427309';
if (cordova.platformId == 'android') {
StatusBar.backgroundColorByHexString(colorCode);
NavigationBar.backgroundColorByHexString(colorCode);
} else if (cordova.platformId == 'ios') {
window.plugins.webviewcolor.change(colorCode);
}
}

看看这个链接,有时候可能会有帮助。我可以用下面提供的解决方案来解决这个问题。 Https://github.com/apache/cordova-plugin-wkwebview-engine/issues/108

[wkWebView.scrollView setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];

在 wkWebView.UIDlegate = self. uiGenerate 之前; 在 CDVWebViewEngine.m 中