2016-08-17 35 views
7

嗨,我有以下情況之前點擊網址:陣營 - 原生Android的WebView手柄裝入

我展示一個網站低谷反應原生一個的WebView。在此網站上有一個指向PassWallet(.pkpass)文件的鏈接(不是唯一的用例)。當我點擊本網站上的任何鏈接時,我想檢查它是否是其他網站或.pkpass文件或其他。雖然此檢查正在運行,但我不想加載任何內容,只需等到我的功能完成後,我就知道是否應打開網站或打開其他應用或其他內容。我想在JavaScript方面做到這一點,因爲我的整個路由功能在那裏,我認爲react-native是爲這種情況建立的:-)

在iOS上有這個美麗的功能onShouldStartLoadWithRequest正是我所需要的。

_onShouldStartLoadWithRequest(e) { 

    if(checkUrl(e.url)) { 

     let Router = this.props.navigator.props.router; 
     let route = Router.getRouteFromUrl(e.url); 
     this.props.navigator.push(route); 

     return false; 

    } 

    return true; 
} 

我收到事件(e)並可以檢查它試圖加載的網址。我甚至可以用e.navigationType檢查它是否是點擊或其他。

現在在Android上這個功能不存在。在本機端有功能shouldOverrideUrlLoading,但是這個功能沒有在react-native中實現。 我發現下面的GitHub問題/ PR https://github.com/facebook/react-native/pull/6478 我想現在,因爲這個問題是封閉的,因此有解釋,這個函數不能實現。

所以我開始自己找一個方法。我創建了一個顯示WebView的Native UI組件,然後實現此方法。

CustomWebViewManager.java:

package ch.mypackage; 

import android.support.annotation.Nullable; 
import android.webkit.WebView; 

import com.facebook.react.uimanager.SimpleViewManager; 
import com.facebook.react.uimanager.ThemedReactContext; 
import com.facebook.react.uimanager.annotations.ReactProp; 

public class CustomWebViewManager extends SimpleViewManager<CplusWebView> { 

    @Override 
    public String getName() { 
     return "CplusWebView"; 
    } 

    @Override 
    protected CustomWebView createViewInstance(ThemedReactContext reactContext) { 
     return new CustomWebView(reactContext); 
    } 

    @ReactProp(name = "url") 
    public void setUrl(CustomWebView view, @Nullable String url) { 
     view.loadUrl(url); 
    } 

    @ReactProp(name = "javascriptEnabled") 
    public void setJavascriptEnabled(CustomWebView view, boolean enabled) { 
     view.getSettings().setJavaScriptEnabled(enabled); 
    } 

} 

CustomWebView.java

package ch.couponplus; 

import android.util.Log; 
import android.webkit.WebView; 
import android.webkit.WebViewClient; 

import com.facebook.react.bridge.Arguments; 
import com.facebook.react.bridge.ReactContext; 
import com.facebook.react.bridge.WritableMap; 
import com.facebook.react.uimanager.ThemedReactContext; 
import com.facebook.react.uimanager.events.EventDispatcher; 
import com.facebook.react.uimanager.events.RCTEventEmitter; 

public class CustomWebView extends WebView { 

    EventDispatcher eventDispatcher; 
    EventWebClient eventWebClient; 

    public CustomWebView(ThemedReactContext reactContext) { 
     super(reactContext); 
     eventWebClient = new EventWebClient(); 
     setWebViewClient(eventWebClient); 
    } 

    protected class EventWebClient extends WebViewClient { 

     @Override 
     public boolean shouldOverrideUrlLoading(WebView view, String url) { 

      WritableMap event = Arguments.createMap(); 
      event.putString("message", "MyMessage"); 
      ReactContext reactContext = (ReactContext)getContext(); 
      reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
        getId(), 
        "topChange", 
        event); 

      return true; 
     } 

    } 

} 

它將按預期工作。我現在可以觸發JS中的shouldOverrideUrlLoading函數並創建日誌或其他內容。

但我的問題是,我現在如何在Javascript中設置truefalse來控制我的shouldOverrideUrlLoading函數?有沒有可能讓我自己的功能可用?到目前爲止,我只能設法觸發onChange事件?

我只是想和我在iOS中做的一樣:-(也許有人出現並告訴我這是不可能的,無論出於何種原因,但我該怎麼處理或者如何處理這種情況?知道有URL模式,但這麼多,我知道他們不會在這種情況下工作。

我很感激在這一個任何幫助....

回答

7

我展示一個網站低谷在這個 網站上有一個到PassWallet(.pkpass)文件的鏈接(不是唯一的 用例)當我點擊本網站上的任何鏈接時,我想檢查 無論是其他網站還是.pkpass文件或其他。

我有一個類似的問題,以及我想檢查在我的react-native應用程序的webView中單擊的鏈接類型。就像你說的那樣,在iOS側,功能onShouldStartLoadWithRequest,這在Android端不存在。

這是我在Android方面的解決方案。

<WebView 
     source={{uri: this.props.url}} 
     onLoad={this.onLoad.bind(this)} 
     onShouldStartLoadWithRequest={this._onShouldStartLoadWithRequest} 
     onNavigationStateChange = {this._onShouldStartLoadWithRequest} 
    /> 

然後,你可以做這樣的事情:

_onShouldStartLoadWithRequest(e) { 

if(checkUrl(e.url)) { 

    let Router = this.props.navigator.props.router; 
    let route = Router.getRouteFromUrl(e.url); 
    this.props.navigator.push(route); 

    this.refs[WEBVIEW_REF].stopLoading(); // <---- Add a similar line 
    //This will tell your webView to stop processing the clicked link 

    return false; 

} 

return true; 

如果我理解正確你的問題,你想辦法查詢的網址在網頁視圖點擊,然後再決定基於URL進行或停下來做別的事情。解決方案超出了我在應用程序中處理它的方式。

看看下面的鏈接:

https://facebook.github.io/react-native/docs/webview.html#stoploading https://github.com/facebook/react-native/pull/6886

+0

謝謝您的回答。這是一個非常好的解決方案,我在其他情況下使用它,例如有鏈接時,我希望它在我自己的視圖中打開,而不是在瀏覽器中打開。但是如果你想打開一個不是像.pkpass文件那樣的網頁的鏈接,應用程序會崩潰,因爲它開始加載鏈接,然後才能停止它。使用iOS功能,您可以在執行任何操作之前停止請求。至於我可以測試這種情況'onNavigationStateChange'在第一次加載請求後被調用。或者當您點擊無效鏈接時,您是否找到了停止加載的方法? – vanBrunneren

+0

我能想到解決這個問題的唯一方法就是停止使用'stopLoading'函數加載webview。但是接下來你會說'onNavigationStateChage'在加載請求後被調用,所以在調用'stopLoading()'的時候 - 可能已經太晚了,應用程序會崩潰。 但我會嘗試一次,看看上面的解決方案是否工作。 –

+0

我不能確切地說哪個函數會在哪個時間被調用,但我可以看到應用程序崩潰之前,我可以停止它,只要我想打開一個像.pkpass一樣的鏈接 – vanBrunneren