1. 程式人生 > >cocos2dx之WebView踩過的坑(android返回鍵處理問題)

cocos2dx之WebView踩過的坑(android返回鍵處理問題)

lib mar 是否 12px blog tex clas ons 測試的

  最近遊戲接入了一個私服平臺,由於沒有sdk,所以支付相關的操作需要在網頁端進行,也就是說點擊充值需要在遊戲內部彈出一個網頁,並定位到平臺充值的地址。查閱相關資料後決定使用cocos2dx自帶的WebView來完成這項任務。WebView的使用方式非常簡單,代碼如下:

#include "ui/CocosGUI.h"
using namespace cocos2d::experimental::ui; m_WebView = WebView::create(); // m_WebView為成員變量 m_WebView->setPosition(visibleSize / 2);
m_WebView->setContentSize(visibleSize); 

m_WebView
->loadURL("http://www.baidu.com");

m_WebView
->setScalesPageToFit(true);

m_WebView
->setOnShouldStartLoading([](WebView *sender, const std::string&url)
{
  return true; }); m_WebView->setOnDidFinishLoading([](WebView *sender, const std::string
&url)
{ }); m_WebView
->setOnDidFailLoading([](WebView *sender, const std::string&url)
{
});
this->addChild(m_WebView);

是不是很簡單?但是在測試的時候卻出現了問題。彈出網頁之後,如果點擊返回鍵遊戲就會退出,分析之後發現是View處理返回鍵的默認操作是銷毀當前Activity。理想的效果是在彈出WebView之後,如果點擊返回鍵,先判斷網頁是否可返回,如果可返回就退到上一級網頁,如果不可返回(在最初的網頁),就關閉WebView,返回遊戲。

首先監聽遊戲內部返回鍵,並處理返回鍵邏輯:

bool FirstScene::init()
{
     //註冊捕捉監聽
    auto listenerkeyPad = EventListenerKeyboard::create();
    listenerkeyPad->onKeyReleased = CC_CALLBACK_2(FirstScene::onKeyReleased, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listenerkeyPad, this);
}
 
void FirstScene::onKeyReleased(EventKeyboard::KeyCode keycode, cocos2d::Event *event)
{
    if (keycode == EventKeyboard::KeyCode::KEY_BACKSPACE) 
    {    
        if (m_WebView) // 如果WebView正在顯示                            
        {
            if (m_WebView->canGoBack()) // 判斷是否可返回到上一級網頁
            {
                m_WebView->goBack();
            }
            else
            {
                m_WebView->runAction(RemoveSelf::create());    // 關閉WebView

                m_WebView = nullptr;
            }
        }
        else // 如果處於遊戲主界面
        {
            Director::getInstance()->popScene(); // 結束遊戲
        }  
    }
}

接下來讓WebView彈出來時點擊返回鍵也執行上述邏輯,這要修改WebView源代碼,打開Cocos2dxWebView.java,路徑為:src/org/cocos2dx/lib/Cocos2dxWebView.java

 public Cocos2dxWebView(Context context, int viewTag) {
    super(context);
    this.mViewTag = viewTag;
    this.mJSScheme = "";

    this.setFocusable(true);
    this.setFocusableInTouchMode(true);

    this.getSettings().setSupportZoom(false);

    this.getSettings().setDomStorageEnabled(true);
    this.getSettings().setJavaScriptEnabled(true);

    // `searchBoxJavaBridge_` has big security risk. http://jvn.jp/en/jp/JVN53768697
    try {
        Method method = this.getClass().getMethod("removeJavascriptInterface", new Class[]{String.class});
        method.invoke(this, "searchBoxJavaBridge_");
    } catch (Exception e) {
        Log.d(TAG, "This API level do not support `removeJavascriptInterface`");
    }

    this.setWebViewClient(new Cocos2dxWebViewClient());
    this.setWebChromeClient(new WebChromeClient());
    
    this.setOnKeyListener(new OnKeyListener() 
    {
        @Override
        public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event)
        {
            if (keyCode == KeyEvent.KEYCODE_BACK) // 返回鍵
            {
                Cocos2dxGLSurfaceView.getInstance().onKeyDown(keyCode, KeyEvent) // 調用遊戲主界面的事件監聽函數

                return true; // 攔截事件,禁止事件向下傳遞
            }

            return false; // 其他事件不做處理,繼續傳遞
        }
    });
 }

其中Cocos2dxGLSurfaceView就是遊戲界面的View,當WebView的返回鍵事件觸發時,直接調用遊戲主界面的事件監聽函數,並禁止事件向下傳遞。

cocos2dx之WebView踩過的坑(android返回鍵處理問題)