[Cordova] 移动App 的 ios11 和 iPhoneX 适配

原文链接:https://blog.csdn.net/lovelyelfpop/article/details/79460700

Apple每次退出新尺寸的iphone都会掀起一番适配风波,这次没有下巴但有刘海的iPhoneX更是如此,网传横屏下的适配动画更是令不少人汗颜。

其实对于Native App来说,适配并不算困难(当然追求酷炫效果另算),官方文档有详细的说明,而对于Web App来说,主要还是依靠打开webview的Native App来适配,而这篇文章主要讨论的是Cordova App要如何适配iPhoneX.

没有适配的效果:

1、以前上架的应用,目标编译平台ios10,上面的刘海和下面的横杆自动被黑边覆盖
这里写图片描述

2、目标平台ios11,重新编译的,上下除了黑边还有白边
这里写图片描述

适配步骤如下

更新cordova插件

每次大版本更新和适配,首先都是更新 Cordova 创建,确认使用的 cordova 插件有是否有新的改进, 例如 cordova-plugin-splashscreen, cordova-plugin-statusbar 等

更新 HTML viewport meta

meta 标签中 添加 viewport-fit=cover,这是 ios 11 新增的设置,可以让页面全屏展示。

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

不过我测试的结果和上图一样,仍然有黑边有白边
这里写图片描述

更新启动图

Google 后得知,需要更新启动图为 Launch Storyboard Image,具体参考 iOS 启动图 (launch storyboard images) 规范

<platform name="ios">
  <splash src="res/screen/ios/Default@2x~universal~anyany.png" />
</platform>

效果如下:
这里写图片描述
全屏是全屏了,但是还是有白边

更换旧的 UIWebview 为 WKWebview

更换 webview 只要添加 cordova-plugin-wkwebview-engine 插件

(下述删除线内容废弃,最新版cordova-plugin-wkwebview-engine 插件修复了。)
更换完,还是有点问题,底部有空白,页面高度不是100%。但是如果换成 cordova-plugin-ionic-webview (这是 ionic 开发的 WKWebview 插件的一个变种,主要也是解决 file 跨域的问题),页面是可以全屏的。

于是,参考 cordova-plugin-ionic-webview 修改 cordova-plugin-wkwebview-engine\src\ios\CDVWKWebViewEngine.m,添加一点代码:

// re-create WKWebView, since we need to update configuration
WKWebView* wkWebView = [[WKWebView alloc] initWithFrame:self.engineWebView.frame configuration:configuration];
//------------added begin-------------
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
if (@available(iOS 11.0, *)) {
  [wkWebView.scrollView setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];
}
#endif
//------------added end----------------
wkWebView.UIDelegate = self.uiDelegate;
self.engineWebView = wkWebView;

然后就可以全屏了
这里写图片描述

Ajax 请求全部失败了

更换完 WKWebview,发现所有的请求都失败了。
这是因为 WKWebview 的安全机制:
1、file:// 协议下(app内页面index.html是 file:// 协议浏览的),访问 http/https资源是属于跨域,服务端必须实现CORS 跨域支持才可以。
可是我已经吧服务端实现过CORS了啊,为啥不行?原来是CORS实现不完整,预检请求(Options)没通过
本人公司因为某些原因,改服务端的办法不可取。

2、即使服务端实现了跨域,应用发出的请求头“Origin”是空值。

所幸的是,Oracle 开发了一个 Cordova 插件 cordova-plugin-wkwebview-file-xhr,解决了上面提到的2个问题。
本插件的原理是拦截所有 webview 的请求(XMLHttpRequest),用原生的方式向服务器请求,然后把结果交给 webview。
不过插件默认只拦截 https 请求,如果需要拦截 http 请求,需要增加配置:

<preference name="InterceptRemoteRequests" value="all" />

图片显示不出来了

真机上,图片又显示不出来了。
本来以为是图片下载失败,调试发现,图片已经下载下来了,但是 WKWebview 显示不出已经下载好的本地图片。
然而,模拟器确是正常的。
Google 了一大圈,发现如果图片文件存在的是 Tmp 目录下,也就是 file:///var/mobile/Applications/Container/Data/<GUID of app>/tmp/ 目录,则真机上可以显示图片,其他目录就不行。
那就换成 Tmp 目录。
注:Cordova 可以使用 cordova.file.tempDirectory 这个常量来得到 Tmp 目录的具体路径。

“刘海”适配

Safe-Area,安全区域是 iPhone X 畸形全面屏的产物。虽说是全面屏,但是顶部多了传感器(刘海)和底部 home 键横线,为了让你的应用在 iPhone X 上 面完美运行,你需要将可视元素扩展至填充整个展示窗口(屏幕)上,同时,你也需要保证如按钮、tab bar 等可交互控件,以及一些至关重要的信息不会因为屏幕的圆角而被裁掉,或者被手机的「刘海」和虚拟「Home键」遮住。

利用 苹果提供的 CSS 常量 env(safe-area-inset-*),可以将重要的界面元素避开刘海、圆角和横线。

Safe-Area 的适配,详细方法自己百度。

最终结果如下:
这里写图片描述

其他要注意的

如果用的是 Sencha Touch

框架会对 index.html 页面添加2次 <meta name="viewport">
所以我们无需在 index.html 中手动增加 viewport-fit="cover",而是在框架代码中的一处加上 viewport-fit="cover",并且我们需要删掉框架代码中的一处 ,否则 env(safe-area-inset-*) 这些 CSS 常量无效(即都是0像素)。

  • 要删除的地方:
    文件 touch\src\core\Ext-more.js,删除下面的内容:
/*if (navigator.standalone) {
    addMeta('viewport', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0');
}
else {
    addMeta('viewport', 'initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, minimal-ui');
}
addMeta('apple-mobile-web-app-capable', 'yes');
addMeta('apple-touch-fullscreen', 'yes');*/

不嫌麻烦,可以把 touch 下 sencha-touch.js、sencha-touch-all.js、sencha-touch-all-debug.js、sencha-touch-debug.js 四个文件也改一下

  • 要修改的地方:
    找到文件 MyApp/.sencha/app/microloader/production.js,找到
addMeta('viewport', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no');

改为

addMeta('viewport', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, viewport-fit=cover');

不嫌麻烦,可以把 microloader 下 development.js、testing.js 也改一下

如果是 ExtJS6 Modern

因为 sencha app build native/ios 构建(打包)的结果里面有个 ios.json,这个是 应用的清单文件(里面包含了要加载的js和css文件列表),如下图:
这里写图片描述

app在启动时 index.html 内的引导代码,会先 ajax(XMLHttpRequest) 请求 ios.json,而后根据清单内容才加载 app.jsapp.css 等文件。

但是,因为 WKWebview 的安全机制, index.html 无法请求 file:///..../www/ios.json,脚本错误如下:

XMLHttpRequest cannot load file 'file:///..../www/ios.json'

我们之前不是加了 cordova-plugin-wkwebview-file-xhr 插件,拦截 webview 请求,利用原生方式请求了吗?为什么还不行呢?这是因为 cordova.jsios.json 清单文件中,也就是说 index.html 在加载 ios.json 的时候,cordova 插件还没有生效。

那么,解决办法就是,设法先加载 cordova.js,等插件生效后,再来加载 ios.json 以及后面的 app.jsapp.css

修改步骤:

  1. 在 index.html 的 <head></head> 中加入
<script type="text/javascript" src="cordova.js"></script>

注意放在 <script id="microloader" data-app="...." type="text/javascript" src="bootstrap.js"></script> 之前
如下:
这里写图片描述

  1. cordova.js 从最终 build 后的 ios.json 清单文件中移出
    修改 MyApp\.sencha\app\app.defaults.json
    把这段去掉:
    这里写图片描述
    注:如果是 phonegap,应该删除这里
    这里写图片描述

这样,build 之后的 ios.json 中就没有 cordova.js 了。

  1. 等 cordova 插件生效后,才允许 index.html 加载 ios.json
    修改 MyApp\.sencha\app\Boot.js,将原来的 fetch 函数改名为 _fetch,然后新加一个 fetch 函数:
// 新加一个 `fetch` 函数
fetch: function() {
    var me = this,
        args = arguments;
    if(Ext.platformTags.cordova) { // 如果是 cordova
        document.addEventListener('deviceready', function() { // 等 cordova 插件生效后,才加载
            me._fetch.apply(me, args);
        }, false);
    }
    else {
        me._fetch.apply(me, args);
    }
},

// 原来的 `fetch` 函数改名为 `_fetch`
_fetch: function(url, complete, scope, async) {
    async = (async === undefined) ? !!complete : async;
    var xhr = new XMLHttpRequest(),
        result, status, content, exception = false,
        readyStateChange = function () {
            if (xhr && xhr.readyState == 4) {
                status = (xhr.status === 1223) ? 204 :

如下图:
这里写图片描述

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
Cordova App是一种跨平台的移动应用开发框架,可以基于HTML、CSS和JavaScript构建应用程序,同时支持Android和iOS等多个平台。在Cordova App中,可以通过使用插件来实现跳转功能。 跳转是指从一个页面或应用程序跳转到另一个页面或应用程序。在Cordova App中,可以通过使用插件来实现不同平台的跳转功能。例如,对于Android平台可以使用Cordova的InAppBrowser插件来打开一个浏览器窗口,并在该窗口中加载指定的URL页面。类似地,对于iOS平台可以使用Cordova的SafariViewController插件来打开一个在应用程序内部显示的浏览器窗口。 除了通过插件实现跳转功能,Cordova App还可以通过使用JavaScript代码来实现内部页面之间的跳转。通过使用Cordova提供的页面导航API,可以在不刷新整个应用程序的情况下,实现不同页面之间的跳转。可以通过在JavaScript中使用函数`window.location.href`或`window.location.replace`来修改页面的URL,进而实现页面跳转。 在Cordova App中进行跳转操作时,通常需要注意以下几点: 1. 合理使用跳转功能,避免过多跳转造成用户体验的不流畅。 2. 对于外部跳转,例如打开网页或其他应用程序,需要注意用户隐私和安全问题。 3. 在跳转过程中,可以通过传递参数来实现页面之间的数据传递,从而实现更复杂的业务逻辑。 总之,Cordova App提供了丰富的跳转功能,可以通过插件和JavaScript代码来实现页面之间的跳转。开发者可以根据具体需求选择合适的方法和技术来实现应用程序中的跳转功能。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神秘_博士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值