因为要用一个全屏网页覆盖整个游戏,需要能在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不行,不知道为什么,所以直接用了个全局的函数,以后有空再查