iOS嵌套HTML开发(二)进阶篇
这篇文章我会给大家详细介绍嵌套HTML页面时,该注意的一些问题。详细介绍的问题的原因和解决的方案,部分核心代码我也会贴出来的,希望能给你带一些帮助。
(PS:本文写给未做过嵌套app的猿们,有经验的可直接跳过)
场景一:优化横竖屏的兼容性
当我们嵌套网页时,可能大部分页面不会做横屏模式,只是少数页面需要切换横竖屏。如果是原生开发,只需要在该ViewController类下shouldAutorotate方法中返回yes or no 即可;但是由于我们的项目是由一个WebView来加载,页面的跳转是html本身来控制的,单一的设置shouldAutorotate的返回值只是将全部页面设置,和我们要的效果不一样。所以,我们要知道该html页面具有横竖屏就可以了。
首先定义一个变量来决定横竖屏模式,这里我就定义一个NSString 类型的变量,默认值为0(只有竖屏模式),值为1代表(可切换横竖屏模式)
- (BOOL)shouldAutorotate{
// NSLog(@"_urlNo2:%@",_urlNow);
if([_urlNow isEqualToString:@"1"]){
return YES;
}else{
return NO;
}
}
接下来我们就来根据实际情况来赋值_urlNow了
1.可以由前端直接通过一个接口传过来的值来判断是否横竖屏,具体实现可看我上篇文章;(优点:可直接由前端控制页面是否有横竖屏模式,缺点:如果html页面是在服务器上,每个页面就多一个网络请求)
2.我们可通过具有横竖屏模式html页面的名称来判断,首先通过webview的代理方法shouldStartLoadWithRequest获取request.URL.absoluteString,再通过lastPathComponent截取到页面的名称,最后得到的名称即可判断该页面是否横竖屏模式(相应改变_urlNow的0/1)
还没完呢!!要想做好兼容横竖屏,我们还需要一步,适配重力感应告诉前端需要切换页面的横竖屏模式;
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator{
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
[coordinator animateAlongsideTransition:^(idcontext) {
//计算旋转之后的宽度并赋值
CGSize screen = [UIScreen mainScreen].bounds.size;
//界面处理逻辑
// self.lineChartView.frame = CGRectMake(0, 30, screen.width, 200.0);
//动画播放完成之后
if(screen.width > screen.height){
NSLog(@"横屏");
NSString *js = [NSString stringWithFormat:@"mobile.playerEvent((\'{\"keyCode\":\"landscape\"}\'))"];
NSLog(@"js:%@",js);
[[HomeWebViewController shareManager].webView stringByEvaluatingJavaScriptFromString:js]; }else{
NSLog(@"竖屏");
NSString *js = [NSString stringWithFormat:@"mobile.playerEvent((\'{\"keyCode\":\"portrait\"}\'))"];
NSLog(@"js:%@",js);
[[HomeWebViewController shareManager].webView stringByEvaluatingJavaScriptFromString:js]; } } completion:^(idcontext) {
NSLog(@"动画播放完之后处理");
}];
}
场景二:嵌套原生视频播放器
说到视频播放器,相信大家很熟悉原生开发操作流程。无论是使用<MediaPlayer/MediaPlayer.h>,还是在AVFoundation上建立的AVKit都可以满足基础的功能。
接下来介绍网页嵌套原生播放器!
一般情况下一个嵌套网页的app,它的底层就是我们那个控制器根View,我们的webView在该根View上。但是现在我们需要另一个View去显示我们播放器(这里我用a带指代它),a存在的层级由我们的需要来确定。
网页嵌套播放器也分两种情况:
1.视频播放器上的图标,进度条由原生实现:
这种情况,播放器上面的操作和显示是由原生来控制的,所以层级关系是根view>webView>a(a在webview上,webview在view上);
视频播放那块的播放器我就不贴代码了,可以用原生或者第三方播放器框架来实现
(PS:像嵌套开发,我建议直接使用苹果提供的AVFoundation自定义的播放器AVPlayer)
AVPlayer:可以理解为播放器对象,灵活性好,可以高度化的自定义UI,但它本身不能显示视频,显示需要另一个类AVPlayerLayer来显示,继承于CALayer,下面是摘自官方的一段介绍:
AVPlayer works equally well with local and remote media files.
You can display the visual content of items played by an instance of AVPlayer in a CoreAnimation layer of class AVPlayerLayer.
You can observe the status of a player using key-value observing.
主要是说它支持本地/网络媒体播放,需要CoreAnimation下的AVPlayerLayer来显示视频,我们可以通过KVO监听player的播放状态。
AVPlayerItem:存有相关媒体信息的类,一个视频资源对应一个AVPlayerItem对象,当你需要循环播放多个视频资源时也需创建多个AVPlayerItem对象。建议大家可以多看看官方的英文文档解释(题外话)。
An AVPlayerItem represents the presentation state of an asset that’s played by an AVPlayer object, and lets you observe that state.
AVAsset:主要用于获取多媒体信息,可以理解为一个抽象类,不能直接使用,操作针对它的子类AVURLAsset,根据你视频的url创建一个包含视频媒体信息的AVURLAsset对象。
CMTime:还会用到这个媒体时间相关的类,如有不明白可以看之前一个帖子的解释。
实现了播放器后,我们需要与js交互了,由html调用我们初始化的播放器的接口,传达的基本参数有(视频的链接url,和视频播放器的位置【x坐标,y坐标,w宽,h高】);
2.视频播放器上的图标,进度条由html实现(ps:这种虽然比较麻烦,但推荐使用这种方式;做嵌套的视频通话原理也是这样):
这种情况,播放器上面的操作和显示是由html来控制的,所以层级关系是根view>a view>webView(a先加在view上,再webview加在view上);
注:需要设置
webView.backgroundColor = [UIColor clearColor]
webView.opaque = NO;
不仅仅html通过js传达的基本参数(视频的链接url,和视频播放器的位置【x坐标,y坐标,w宽,h高】),还需要把视频这层<Div>设置透明色,否则会遮挡视频。
接下来就是js和oc的交互(比如点击暂停按钮调用oc的暂停接口),具体的实现可看我的上篇文章。
写到这里嵌套原生播放器完成了??
是的,但是我相信部分人会遇到下面这个问题。
由于我们是嵌套html是大部分由一个控制器(ViewController)来加载,视频页面和其他页面切换时,我们需要手动把视频播放器暂停后再销毁了(上面说的a不需要销毁但需要removeFromSuperview),否则离开播放页面后视频仍然在播放可听到声音或者那个视频播放器视图也一直存在。
最后,我解答部分小伙伴提出的疑惑,苹果会让嵌套的web应用能否通过审核?还是说需要部分嵌套部分原生才行?
在这里我很负责的告诉大家没问题的,苹果审核团队不会因为你页面全部是web实现的打退回来。本人已经上架多个嵌套html的app,包括帮通信运营商开发地页面全部采用html的iOS App都得到了通过,所以说放心地去做移动端原生嵌套开发!