【玩转cocos2d-x之三十三】游戏嵌入Webview网页

手游《我叫MT》一开始会弹出一个游戏公告,有玩过的肯定都蛮熟悉的,这就是webview,就是一个网页。由于webview和平台相关,这里就介绍下cocos2d-x如何嵌入andorid的webview控件,在cocos2d-x中显示网页。

Jni

Jni这里我就不再多说了。可用参考wikipedia,或者微信飞机大战的移植篇。通过Jni,可以实现在cocos2d-x中调用Android的API,当然也可以进行传值。

Android使用webview

直接上代码。主要是处理布局和webview使用的问题。这里采用代码布局。以下操作在android的主类(cocos2dxActivity)中处理。

添加成员变量

整个布局的结构是最底层一个FrameLayout,ImageView控件放置在FrameLayout上。然后之上是一个LinearLayout用来放置关闭按钮,LinearLayout往下是Webview控件。

成员变量
1
2
3
4
5
6
static Test test  = null;//Test实例
WebView m_webView;//WebView控件
ImageView m_imageView;//ImageView控件
FrameLayout m_webLayout;//FrameLayout布局
LinearLayout m_topLayout;//LinearLayout布局
Button m_backButton;//关闭按钮

OnCreate中添加FrameLayout布局

添加FrameLayout布局
1
2
3
4
5
6
7
8
9
10
protected void onCreate(Bundle savedInstanceState){  
super.onCreate(savedInstanceState);
test=this;

//初始化一个空布局
m_webLayout = new FrameLayout(this);
FrameLayout.LayoutParams lytp = new FrameLayout.LayoutParams(800,640);
lytp .gravity = Gravity.CENTER;
addContentView(m_webLayout, lytp);
}

返回实例

返回实例
1
2
3
4
public static Test getInstance() {
Log.v("TestJacky","getInstance");
return test;
}

显示webview

显示webview
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public void openWebview() {  
Log.v("TestJacky", "openWebView");
this.runOnUiThread(new Runnable() {//在主线程里添加别的控件
public void run() {
//初始化webView
m_webView = new WebView(test);
//设置webView能够执行javascript脚本
m_webView.getSettings().setJavaScriptEnabled(true);
//设置可以支持缩放
m_webView.getSettings().setSupportZoom(true);//设置出现缩放工具
m_webView.getSettings().setBuiltInZoomControls(true);
//载入URL
m_webView.loadUrl("http://m.blog.csdn.net/blog/jackyvincefu/");
//使页面获得焦点
m_webView.requestFocus();
//如果页面中链接,如果希望点击链接继续在当前browser中响应
m_webView.setWebViewClient(new WebViewClient(){
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(url.indexOf("tel:")<0){
view.loadUrl(url);
}
return true;
}
});

//背景图
m_imageView = new ImageView(test);
m_imageView.setImageResource(R.drawable.bkgnd);
m_imageView.setScaleType(ImageView.ScaleType.FIT_XY);
//初始化线性布局 里面加按钮和webView
m_topLayout = new LinearLayout(test);
m_topLayout.setOrientation(LinearLayout.VERTICAL);
//初始化返回按钮
m_backButton = new Button(test);
m_backButton.setBackgroundResource(R.drawable.btn);
LinearLayout.LayoutParams lypt=new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
lypt.gravity=Gravity.RIGHT;
m_backButton.setLayoutParams(lypt);
m_backButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
removeWebView();
}
});
//把image加到主布局里
m_webLayout.addView(m_imageView);
//把webView加入到线性布局
m_topLayout.addView(m_backButton);
m_topLayout.addView(m_webView);
//再把线性布局加入到主布局
m_webLayout.addView(m_topLayout);
}
});
}

移除webview

移除webview
1
2
3
4
5
6
7
8
9
10
11
12
13
public void removeWebView() {                
m_webLayout.removeView(m_imageView);
m_imageView.destroyDrawingCache();

m_webLayout.removeView(m_topLayout);
m_topLayout.destroyDrawingCache();

m_topLayout.removeView(m_webView);
m_webView.destroy();

m_topLayout.removeView(m_backButton);
m_backButton.destroyDrawingCache();
}

重写返回键

重写返回键
1
2
3
4
5
6
7
8
9
10
public boolean onKeyDown(int keyCoder,KeyEvent event)  
{

//如果网页能回退则后退,如果不能后退移除WebView
if(m_webView.canGoBack() && keyCoder == KeyEvent.KEYCODE_BACK){
m_webView.goBack();
}else{
removeWebView();
}
return false;
}

cocos2d-x使用Jni

这里直接使用HelloWorld的示例,修改了close按钮的回调函数。

jni头文件

jni头文件
1
2
3
4
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)  
#include <jni.h>
#include "platform/android/jni/JniHelper.h"
#endif

Jni调用打开webview

Jni调用打开webview
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void HelloWorld::menuCloseCallback(CCObject* pSender)  
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
JniMethodInfo minfo;
//getStaticMethodInfo,判断Java静态函数是否存在,并且把信息保存到minfo里
//参数1:JniMethodInfo
//参数2:Java类包名+类名
//参数3:Java函数名称
//参数4:函数参数类型和返回值类型
bool isHave = JniHelper::getStaticMethodInfo(minfo,"com/jacky/test/Test","getInstance","()Lcom/jacky/test/Test;");
jobject jobj;//存对象
if (isHave) {
//这里的调用getInstance,返回Test类的对象。
jobj = minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID);

isHave = JniHelper::getMethodInfo(minfo,"com/jacky/test/Test","openWebview","()V");
if (isHave) {
//调用openWebview, 参数1:Test对象 参数2:方法ID
minfo.env->CallVoidMethod(jobj, minfo.methodID);
}
}
#else
CCDirector::sharedDirector()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
#endif
}

效果图

爪机截屏的。







ps:这里没有处理多次打开webview的情况。可以采用Jni方法来通知cocos2d-x,也可以直接在主类中设置一个成员变量标志位,调用openWebview时设置为true,removeWebView时设置为false,在调用openWebview时检测这个标志位来决定是否打开即可。

源码下载

包含win32,android代码,拿掉了android交叉编译生成的obj,保留so和apk文件。

下载地址

文章目录
  1. 1. Jni
  2. 2. Android使用webview
    1. 2.1. 添加成员变量
    2. 2.2. OnCreate中添加FrameLayout布局
    3. 2.3. 返回实例
    4. 2.4. 显示webview
    5. 2.5. 移除webview
    6. 2.6. 重写返回键
  3. 3. cocos2d-x使用Jni
    1. 3.1. jni头文件
    2. 3.2. Jni调用打开webview
  4. 4. 效果图
  5. 5. 源码下载
,