因为要用一个全屏网页覆盖整个游戏,需要能在js里直接调用lua的函数,网上搜了一圈没有发现怎样实现回调,自己写了份,共享给大家
1,把代码中的webview调通并且到处到lua,这步请自行搜索,网上一堆教程,这样就可以在lua中调用webview的大部分函数了
2,将几个需要回调的函数手动绑定,我因为只需要三个,就导出了setJsCallback,setOnDidCallback和setOnFailCallback
把下面的代码加入到lua_cocos2dx_ui_manual.cpp中
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
static int handleWebViewJSEvent(int handler, WebView* sender, const std::string& js)
{
LuaStack* stack = LuaEngine::getInstance()->getLuaStack();
stack->pushObject(sender, "ccui.WebView");
stack->pushString(js.c_str());
stack->executeFunctionByHandler(handler, 2);
stack->clean();
return 0;
}
static int lua_cocos2dx_WebView_setJSCallback(lua_State* L)
{
if (nullptr == L)
return 0;
int argc = 0;
WebView* self = nullptr;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
if (!tolua_isusertype(L,1,"ccui.WebView",0,&tolua_err)) goto tolua_lerror;
#endif
self = static_cast(tolua_tousertype(L,1,0));
#if COCOS2D_DEBUG >= 1
if (nullptr == self) {
tolua_error(L,"invalid 'self' in function 'lua_cocos2dx_WebView_setJSCallback'\n", NULL);
return 0;
}
#endif
argc = lua_gettop(L) - 1;
if (1 == argc)
{
#if COCOS2D_DEBUG >= 1
if (!toluafix_isfunction(L,2,"LUA_FUNCTION",0,&tolua_err))
{
goto tolua_lerror;
}
#endif
LUA_FUNCTION handler = ( toluafix_ref_function(L,2,0));
self->setOnJSCallback(=](WebView *sender, const std::string &url){
//CCLOG("OnJSCallback");
handleWebViewJSEvent(handler, sender, url);
});
ScriptHandlerMgr::getInstance()->addCustomHandler((void*)self, handler);
return 0;
}
luaL_error(L, "'setJSCallback' function of WebView has wrong number of arguments: %d, was expecting %d\n", argc, 1);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(L,"#ferror in function 'setJSCallback'.",&tolua_err);
return 0;
#endif
}
static int lua_cocos2dx_WebView_setOnDidCallback(lua_State* L)
{
if (nullptr == L)
return 0;
int argc = 0;
WebView* self = nullptr;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
if (!tolua_isusertype(L,1,"ccui.WebView",0,&tolua_err)) goto tolua_lerror;
#endif
self = static_cast(tolua_tousertype(L,1,0));
#if COCOS2D_DEBUG >= 1
if (nullptr == self) {
tolua_error(L,"invalid 'self' in function 'lua_cocos2dx_WebView_setOnDidCallback'\n", NULL);
return 0;
}
#endif
argc = lua_gettop(L) - 1;
if (1 == argc)
{
#if COCOS2D_DEBUG >= 1
if (!toluafix_isfunction(L,2,"LUA_FUNCTION",0,&tolua_err))
{
goto tolua_lerror;
}
#endif
LUA_FUNCTION handler = ( toluafix_ref_function(L,2,0));
self->setOnDidFinishLoading(=](WebView *sender, const std::string &url){
//CCLOG("OnJSCallback");
handleWebViewJSEvent(handler, sender, url);
});
ScriptHandlerMgr::getInstance()->addCustomHandler((void*)self, handler);
return 0;
}
luaL_error(L, "'setOnDidCallback' function of WebView has wrong number of arguments: %d, was expecting %d\n", argc, 1);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(L,"#ferror in function 'setOnDidCallback'.",&tolua_err);
return 0;
#endif
}
static int lua_cocos2dx_WebView_setOnFailCallback(lua_State* L)
{
if (nullptr == L)
return 0;
int argc = 0;
WebView* self = nullptr;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
if (!tolua_isusertype(L,1,"ccui.WebView",0,&tolua_err)) goto tolua_lerror;
#endif
self = static_cast(tolua_tousertype(L,1,0));
#if COCOS2D_DEBUG >= 1
if (nullptr == self) {
tolua_error(L,"invalid 'self' in function 'lua_cocos2dx_WebView_setOnFailCallback'\n", NULL);
return 0;
}
#endif
argc = lua_gettop(L) - 1;
if (1 == argc)
{
#if COCOS2D_DEBUG >= 1
if (!toluafix_isfunction(L,2,"LUA_FUNCTION",0,&tolua_err))
{
goto tolua_lerror;
}
#endif
LUA_FUNCTION handler = ( toluafix_ref_function(L,2,0));
self->setOnDidFailLoading(=](WebView *sender, const std::string &url){
//CCLOG("OnJSCallback");
handleWebViewJSEvent(handler, sender, url);
});
ScriptHandlerMgr::getInstance()->addCustomHandler((void*)self, handler);
return 0;
}
luaL_error(L, "'setOnFailCallback' function of WebView has wrong number of arguments: %d, was expecting %d\n", argc, 1);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(L,"#ferror in function 'setOnFailCallback'.",&tolua_err);
return 0;
#endif
}
static void extendWebView(lua_State* L)
{
lua_pushstring(L, "ccui.WebView");
lua_rawget(L, LUA_REGISTRYINDEX);
if (lua_istable(L,-1))
{
tolua_function(L, "setJsCallback", lua_cocos2dx_WebView_setJSCallback);
tolua_function(L, "setOnDidCallback", lua_cocos2dx_WebView_setOnDidCallback);
tolua_function(L, "setOnFailCallback", lua_cocos2dx_WebView_setOnFailCallback);
}
lua_pop(L, 1);
}
#endif
```
3 将extendWebView函数加入到register_all_cocos2dx_ui_manual中进行注册
int register_all_cocos2dx_ui_manual(lua_State* L)
{
if (nullptr == L)
return 0;
extendWidget(L);
extendCheckBox(L);
extendSlider(L);
extendTextField(L);
extendPageView(L);
extendScrollView(L);
extendListView(L);
extendLayoutParameter(L);
extendEditBox(L);
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
extendWebView(L);
#endif
return 0;
}
4 在lua中调用webview代码
local platform = cc.Application:getInstance():getTargetPlatform()
if cc.PLATFORM_OS_ANDROID ~= platform then
return
end
web = ccui.WebView:create()
function jsCallback(sender, str)
print("jsCallback ", str)
if str == "lua://CloseHelp.lobby.command" then
web:setVisible(false)
end
end
local function didCallback(sender, str)
print("didCallback ", str)
end
local function failCallback(sender, str)
print("failCallback ", str)
end
web:setPosition(400,300)
web:setContentSize(800,600)
web:loadURL("http://www.baidu.com")
web:setJavascriptInterfaceScheme("lua")
web:setJsCallback(jsCallback)
web:setOnDidCallback(didCallback)
web:setOnFailCallback(failCallback)
mainScene:addChild(web)
web:setVisible(false)
--web:evaluateJS("alert(\"hello\")")
```
5 注意事项
web:setJavascriptInterfaceScheme("lua")这个lua代表协议的类型,如http://baidu.com 这个值就是http,我们设置一个lua开头scheme,js里打开的所有链接,只要是lua开头的就会送回webview的callback
处理,而不会真的去打开链接。所以,要lua执行关闭的函数,直接在js网页中打开链接 "lua://CloseHelp.lobby.command"
web:evaluateJS("alert(\"hello\")") --使用此函数可以调用JavaScript中的函数
web:setJsCallback(jsCallback) 这个函数用local function不行,不知道为什么,所以直接用了个全局的函数,以后有空再查