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

Posted

技术标签:

【中文标题】Cordova 应用程序无法在 iPhone X(模拟器)上正确显示【英文标题】:Cordova app not displaying correctly on iPhone X (Simulator) 【发布时间】:2018-02-24 05:55:49 【问题描述】:

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

添加 cordova-plugin-wkwebview-engine 以便 Cordova 使用 WKWebView(不是 UIWebView)进行渲染修复了白条。 由于使用cordova-plugin-wkwebview-engine 时出现的性能和内存泄漏问题,我的应用程序没有从 UIWebView 迁移到 WKWebView WKWebView 中的安全限制,因此必须通过cordova-plugin-file 加载图像数据。

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

(来源:pbrd.co)

(来源:pbrd.co)

与填充全屏区域的本机应用程序相比,两个 Cordova Webview 都显示黑色区域:

【问题讨论】:

对 wkwebview 很感兴趣。在我的游戏中,我没有全宽,但也偏离了中心。在 uiwebview 中,它保持相同的大小,但至少居中。 我也遇到了这个问题,所以我只用 css 做了一些解决方法参见pt.***.com/a/263460/55076 我也有这个问题。只需将<meta> 标记添加到我的cordova index.hml 文件中,因为下面列出的其他标记不起作用。我正在使用 cordova-ios 4.5.4 运行 Cordova 7x - 还有什么我需要做的吗? 【参考方案1】:

我找到了解决白条here的方法:

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

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

UIWebView 中的白条随即消失:

删除黑色区域的解决方案(在下面的评论中由@dpogue 提供)是使用LaunchStoryboard images 和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 不同的问题需要解决:由于“缺口”,状态栏大于 20 像素,这意味着您的 Cordova 应用程序最顶部的任何内容都将被它遮住了:

您可以使用 iOS 11 中的新 safe-area-inset-* 常量在 CSS 中自动处理此问题,而不是硬编码以像素为单位的填充。

注意:在 iOS 11.0 中处理这些常量的函数被称为 constant(),但在 iOS 11.2 中,Apple 将其重命名为 env() (see here), 因此,要涵盖这两种情况,您需要同时使用这两种情况重载 CSS 规则,并依靠 CSS fallback mechanism 来应用适当的一种:

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 按钮重叠。 就我而言,我无法将其应用于&lt;body&gt;,因为页脚是绝对定位的,因此我需要将其直接应用于页脚:

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

cordova-plugin-statusbar

iPhone X 上的状态栏大小已更改,因此旧版本的cordova-plugin-statusbar 在 iPhone X 上显示不正确 Mike Hartington 已创建 this pull request,它应用了必要的更改。 此版本已合并到 cordova-plugin-statusbar@2.3.0 版本中,因此请确保您至少使用此版本以应用于安全区域插入

闪屏

iOS 11/iPhone X 上的 LaunchScreen 故事板约束发生了变化,这意味着在使用现有版本的插件 (see here) 时,启动画面似乎会“跳跃”。 这已在错误报告 CB-13505 中捕获,已修复 PR cordova-ios#354 并在 cordova-ios@4.5.4 中发布,因此请确保您使用的是最新版本的 cordova-ios 平台。

设备方向

在 iOS 11.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

【讨论】:

旋转屏幕有什么问题吗?我一直在尝试,但是在旋转屏幕之后,一切都被破坏了(安全区域插入*不会根据设备方向更新它们的值;并且在再次旋转纵向->横向->纵向之后,初始值也被破坏了)。苹果/Safari浏览器可能有问题吗? 就我而言,当我添加viewport-fit=cover 时,我的整个应用程序只显示一个空白的白色屏幕,没有别的。我在 iPhone 7 Plus 上使用 iOS11、Xcode9。有人遇到过类似行为吗? @DaveAlden - 看起来在 11.2 beta+ 中,他们已经为 env 关键字删除了 constant - 另请参阅:webkit.org/blog/7929/designing-websites-for-iphone-x 你把body css代码放在你的应用程序的什么地方?比如在哪个文件?什么都不适合我,我正在使用 Ionic 3。 是否有关于轮换问题的更新?我在 iOS 12 上遇到了同样的问题。我觉得这个问题仍然存在很奇怪。 /cc @jms【参考方案2】:

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

黑条

将此添加到您的 info.plist 文件中。修复启动图像是一个单独的问题,即How to Add iPhoneX Launch Image

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

白条

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

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

【讨论】:

谢谢! .plist 更改与所选答案的更改具有相同的效果,但速度更快。 这些任务对 CSS 像素高度和宽度有什么影响?我的应用程序顶部有一系列窄 div(菜单等)......然后我计算剩余的像素高度以使最后一个 DIV 填充屏幕的其余部分。现在我可以看到下方的白色条覆盖了该 DIV 的一部分,但我也不能告诉所有这些 - 这意味着 DIV 仍然没有进入屏幕底部。反过来,我的应用程序从上方的白条下方开始,因此它甚至不会尝试使用上方的空间。 我使用了UILaunchStoryboardName,它设法去除了黑条。但是我的启动画面被扩大了。有什么理由吗?接受的答案对我不起作用 @coder 谢谢 - 但是将 UILaunchStoryboardName 添加到 plist 会阻止我提交到应用商店:错误 ITMS-90705:“未找到启动故事板。确保指定启动故事板文件名Info.plist 中的键 UILaunchStoryboardName 没有文件扩展名。” @Huiting 你的案子有没有找到解决办法?【参考方案3】:

您必须执行 3 个步骤

对于 iOs 11 状态栏和 iPhone X 标题问题


1.视口适配盖

viewport-fit=cover 添加到&lt;header&gt; 中的视口元数据

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


    向您的config.xml 内的&lt;platform name="ios"&gt; 添加更多启动图像

不要跳过这一步,这是为 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)


    在 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);


奖励:您可以在deviceready 上添加像is-androidis-ios 这样的body 类

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

所以你可以在 CSS 上做这样的事情

.is-ios #header 
 // Properties

【讨论】:

【参考方案4】:

在我的情况下,每个初始屏幕都是单独设计的,而不是自动生成的或以故事板格式布置的,我不得不坚持我的旧版启动屏幕配置,并添加纵向和横向图像以将 iPhoneX 1125×2436 方向定位到config.xml 像这样:

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

将这些添加到 config.xml 后(“viewport-fit=cover”已在 index.hml 中设置),我使用 Ionic Pro 构建的应用会填满 iPhoneX 设备上的整个屏幕。

【讨论】:

先生,但在我的 config.xml 中,我已经在这一行上方添加了 viewport-fit=cover @Kapilsoni 那么可能是 Cordova UIWebView、WKWebView、SplashScreen 插件或这些配置的组合存在问题。另外,您在构建中的目标是 XCode 10 还是 11? 先生,我的目标是 XCode 10 吗?【参考方案5】:

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

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

【讨论】:

【参考方案6】:

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

在 iPhone X/XS 上,屏幕旋转会导致标题栏高度使用不正确的值,因为计算 safe-area-inset-* 没有及时反映 UI 刷新的新值。即使在最新的 iOS 12 中,UIWebView 中也存在此错误。解决方法是插入 1px 上边距,然后快速反转它,这将触发 safe-area-inset-* 立即重新计算。一个有点丑陋的修复,但如果您出于某种原因必须使用 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.marginTop 稍微改变一下然后反转。它不一定必须是“1px”。您可以选择一个不会导致 UI 闪烁但能达到目的的值。

【讨论】:

UIWebView 在 iOS8 中被贬低了......我怀疑是否会修复任何现有的错误。 Apple 在上传应用程序时警告说,这将很快停止......因此是时候忍受痛苦并迁移到 WKWebView......【参考方案7】:

我正在开发 Cordova 应用程序 2 年,我花了数周时间来解决相关问题(例如:打开键盘时 webview 滚动)。这是适用于 ios 和 android 的经过测试和验证的解决方案

P.S.:我使用 iScroll 来滚动内容

    切勿在 index.html 的元标记中使用 viewport-fit=cover,让应用远离状态栏。 iOS 将为所有 iPhone 变体处理适当的区域。 在 XCode 中取消选中 隐藏状态栏需要全屏,不要忘记选择 Launch Screen File 作为 CDVLaunchScreen 在 config.xml 中将 fullscreen 设置为 false 最后,(感谢 Eddy Verbruggen 提供的出色插件)添加他的插件 cordova-plugin-webviewcolor 以设置状态栏和底部区域的背景颜色。这个插件可以让你设置任何你想要的颜色。

    在 config.xml 中添加以下内容(x 之后的第一个 ff 为不透明度)

    <preference name="BackgroundColor" value="0xff088c90" />
    

    通过向输入元素添加焦点事件自行处理滚动位置

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

对于 android,执行相同操作,但不要安装 cordova-plugin-webviewcolor,而是安装 cordova-plugin-statusbarcordova-plugin-navigationbar-color

这是使用这些插件在 ios 和 android 上工作的 javascript 代码:

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);
    

【讨论】:

【参考方案8】:

如果您在全局范围内安装较新版本的ionic,您可以运行 ionic cordova resources 它将为您生成所有初始屏幕图像以及正确的尺寸。

【讨论】:

【参考方案9】:

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

添加

[wkWebView.scrollView setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];

之前 wkWebView.UIDelegate = self.uiDelegate;在 CDVWebViewEngine.m

【讨论】:

以上是关于Cordova 应用程序无法在 iPhone X(模拟器)上正确显示的主要内容,如果未能解决你的问题,请参考以下文章

toISOString 在 iPhone 中无法与 Cordova Ionic 一起使用

cordova/phonegap 屏幕缺口检测(适用于所有手机,不仅适用于 iPhone X)

初始化时iPhone X上显示的两个不同的启动屏幕

IOS : Cordova App Crash on Google Map api zoom in ios 11.3 iphone x

Cordova iOS 11.0 Iphone X 状态栏差距

Cordova iPhone X 状态栏添加白色空栏