由于cocos2dx-2.2.6引擎中没有提供WebView控件,只能通过与iOS和Android交互来显示网页。
需求说明:在某个Layer中点击打开网页按钮时,在指定位置加载指定大小的网页(已经加载过的显示出来就行);点击Layer中其他功能按钮时,隐藏网页;点击关闭Layer按钮时移除网页。
由于我们的项目是按照1136x640尺寸来横屏布局的,所以相关的(X, Y, W, H)也是相对于1136x640尺寸来说,iOS上需要根据实际屏幕尺寸来适配。但是,cocos2dx中坐标系与iOS中坐标系分别是这样的:锚点A不一样(默认状态下cocos2dx中一般控件在中心点,panel、layer在左下角,也可自定义),也就是需要设置坐标的点,用来确定控件的位置。传坐标给iOS时,就按照iOS坐标系来传值:X值就是控件顶点(左上角)距离左边的距离,Y值就是控件顶点(左上角)距离顶部的距离。
另外,cocos2dx中采用 缩放比例scale = screenW/1136 与 screenH/640 中的小值;那么在iOS中也采用这种适配方式。
kResolutionShowAll MIN(横向比,纵向比) 拉伸 ,会出现黑边
kResolutionExactFit 横向按横向比拉伸,纵向按纵向比拉伸
利用Jni实现C++与iOS交互
Cocos2dx游戏端:
在JniCmd.h文件中,定义消息变量:
#define CMD_CTJ_OPEN_SMALL_WEB 20114 //打开内嵌网页
#define CMD_CTJ_CLOSE_SMALL_WEB 20115 //关闭(隐藏)内嵌网页
#define CMD_CTJ_REMOVE_SMALL_WEB 20116 //移除内嵌网页
在JniSink.h文件中声明方法:
// 打开内嵌网页:链接,顶点坐标x,y,网页大小w,h
void OpenSmallWeb(cocos2d::CCObject *pTarget, SEL_CallFuncJni pSEL_CallFuncJni,const char*szUrl,int iX, int iY, int iWidth, int iHeight );
// 关闭内嵌网页
void CloseSmallWeb();
// 移除内嵌网页
void removeSmallWeb();
在JniSink.cpp文件中实现方法:
void JniSink::OpenSmallWeb( cocos2d::CCObject *pTarget, SEL_CallFuncJni pSEL_CallFuncJni,const char*szUrl, int iX, int iY, int iWidth, int iHeight )
{
addJniRes(pTarget, pSEL_CallFuncJni);
char szBuf[240];
sprintf(szBuf, "%s,%d,%d,%d,%d",szUrl, iX, iY, iWidth, iHeight);
#if ( CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
callJavaCommand(CMD_CTJ_OPEN_SMALL_WEB, szBuf);
#elif ( CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
ObjectCHelper::share()->cppCallOc(CMD_CTJ_OPEN_SMALL_WEB, szBuf);
#else
//javaCallback(CMD_CTJ_OPEN_SMALL_WEB, "1");
#endif
}
void JniSink::CloseSmallWeb()
{
#if ( CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
callJavaCommand(CMD_CTJ_CLOSE_SMALL_WEB, NULL);
#elif ( CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
ObjectCHelper::share()->cppCallOc(CMD_CTJ_CLOSE_SMALL_WEB, NULL);
#else
#endif
}
void JniSink::removeSmallWeb()
{
#if ( CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
callJavaCommand(CMD_CTJ_REMOVE_SMALL_WEB, NULL);
#elif ( CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
ObjectCHelper::share()->cppCallOc(CMD_CTJ_REMOVE_SMALL_WEB, NULL);
#else
#endif
}
具体的Layer中调用:
JniSink::share()->OpenSmallWeb(this, callfuncjni_selector(NewInfoLayer::JniCallback), szURL, 305, 103, 718, 452);
JniSink::share()->CloseSmallWeb();
JniSink::share()->removeSmallWeb();
iOS端,自定义WebViewHeler单利类:
把UIWebView加到[UIApplication sharedApplication].keyWindow.rootViewController.view上,也可以直接加到[UIApplication sharedApplication].keyWindow上
WebViewHeler.h文件
#import
@interface WebViewHelper : NSObject
@property (nonatomic, strong) UIWebView *webView;
@property (nonatomic, assign) BOOL bHidden;
+ (instancetype)sharedWebViewHelper;
- (void)loadWebViewWithParam:(NSString * )param;
- (void)removeVebView;
@end
WebViewHeler.mm文件(.mm结尾的文件,可进行cocos2dx与iOS混编)
+ (instancetype)sharedWebViewHelper{
static id instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
- (void)loadWebViewWithParam:(NSString * )param{
// 分割字符串
NSArray *arr = [param componentsSeparatedByString:@","];
// 获取链接字符串
NSString *httpStr = arr.firstObject;
NSLog(@"httpStr %@", httpStr);
// 获取生成frame
// 参数传的是5、5s的实际像素,是物理尺寸2倍
if (arr.count < 5) {
return;
}
// 改成单倍尺寸
CGFloat x = [arr[1] floatValue]/2;
CGFloat y = [arr[2] floatValue]/2;
CGFloat width = [arr[3] floatValue]/2;
CGFloat height = [arr[4] floatValue]/2;
CGFloat scaleX = kScreenWidth / 568.0f;
CGFloat scaleY = kScreenHeight / 320.0f;
// 防止横屏状态下,获取的宽和高是竖屏状态下的宽和高,目的是确定 W > H
if (kScreenWidth < kScreenHeight) {
scaleX = kScreenHeight / 568.0f;
scaleY = kScreenWidth / 320.0f;
}
//如果游戏按照 MIN(横向比,纵向比) 拉伸,则 width x height y 分别为:
CGFloat scale = scaleX < scaleY ? scaleX : scaleY;
width *= scale;
x *= scale;
height *= scale;
y *= scale;
//如果游戏按照横向纵向拉伸适配,则 width x height y 分别为:
//width *= scaleX;
//x *= scaleX;
//height *= scaleY;
//y *= scaleY;
CGRect newframe = CGRectMake(x, y, width, height);
NSLog(@"width = [%f] height = [%f] x = [%f] y = [%f]", width, height, x, y);
// 加载网页
self.webView = [[UIWebView alloc] initWithFrame:newframe];
self.webView.backgroundColor = [UIColor colorWithRed:50/256.0 green:57/256.0 blue:96/256.0 alpha:1];
self.webView.scalesPageToFit = YES;
self.webView.scrollView.bounces = NO;
self.webView.delegate =self;
// 根据需要给webView 切圆角,这里采用贝塞尔曲线
self.webView = [self clipCornerWithView:self.webView andTopLeft:YES andTopRight:YES andBottomLeft:YES andBottomRight:YES];
NSURLRequest *urlRequest = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:httpStr]];
// 添加webView到根视图
[[UIApplication sharedApplication].keyWindow.rootViewController.view addSubview:self.webView];
// 开始请求
[self.webView loadRequest:urlRequest];
self.webView.hidden = true;
self.bHidden = true;
// 测试本地
// [self loadLocalHtml:self.webView fileName:httpStr];
}
#pragma mark - WebView Delegate
- (void)webViewDidStartLoad:(UIWebView *)webView{
if (self.webView.isLoading) {
return;
}
NSLog(@"开始加载");
}
- (void)webViewDidFinishLoad:(UIWebView *)webView{
if (self.bHidden == false) {
return;
}
NSLog(@"加载完成");
self.bHidden = false;
self.webView.hidden = false;
// 告诉Cocos2dx 加载成功
ObjectCHelper::share()->ocCallCpp(CMD_CTJ_OPEN_SMALL_WEB, "1");
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
NSLog(@"加载失败");
// 告诉Cocos2dx 加载失败
ObjectCHelper::share()->ocCallCpp(CMD_CTJ_OPEN_SMALL_WEB, "0");
// webView加载失败后,置为nil,重新加载时会重新创建
self.webView = nil;
}
iOS中 处理OC与C++交互的类 ObjectCHelper.mm文件 调用OC方法
ObjectCHelper *ObjectCHelper::g_pObjectCHelper = NULL;
ObjectCHelper *ObjectCHelper::share(){
if (g_pObjectCHelper == NULL) {
g_pObjectCHelper = new ObjectCHelper;
}
return g_pObjectCHelper;
}
std::string ObjectCHelper::cppCallOc(const int cmd, const char *szParam){
if (CMD_CTJ_OPEN_SMALL_WEB== cmd){
if(szParam){
// webView存在就显示出来,不存在就重新加载
if([WebViewHelper sharedWebViewHelper].webView ){
[WebViewHelper sharedWebViewHelper].webView.hidden = false;
ObjectCHelper::share()->ocCallCpp(CMD_CTJ_OPEN_SMALL_WEB, "1");
}else{
NSString *strList = [NSString stringWithUTF8String:szParam];
[[WebViewHelper sharedWebViewHelper] loadWebViewWithParam:strList];
}
}
}else if (CMD_CTJ_CLOSE_SMALL_WEB== cmd){
if([WebViewHelper sharedWebViewHelper].webView ){
[WebViewHelper sharedWebViewHelper].webView.hidden = true;
}
}else if (CMD_CTJ_REMOVE_SMALL_WEB== cmd){
[[WebViewHelper sharedWebViewHelper] removeVebView];
}
}
void ObjectCHelper::ocCallCpp(const int cmd, const char *szParam){
JniSink::share()->javaCallback(cmd, szParam);
}
cocos2dx嵌入安卓平台webView的方法