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 按钮重叠。
就我而言,我无法将其应用于<body>
,因为页脚是绝对定位的,因此我需要将其直接应用于页脚:
.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
添加到<header>
中的视口元数据
<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
内的<platform name="ios">
添加更多启动图像
不要跳过这一步,这是为 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-left
、safe-area-inset-right
、safe-area-inset-top
或safe-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-android
或is-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-statusbar 和 cordova-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)
IOS : Cordova App Crash on Google Map api zoom in ios 11.3 iphone x