javascript - React-native android WebView 在加载前处理点击的 Url

标签 javascript android reactjs webview react-native

我在 react-native 中通过 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) 并且可以检查它正在尝试加载的 url。我什至可以使用 e.navigationType 检查是点击还是其他原因。

现在安卓上没有这个功能。在 native 端有函数 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);
    }

}

自定义WebView.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 模式,但我知道它们在这种情况下不起作用。

最佳答案

I'm showing a Website trough a WebView in react-native. On this Website there is a link to a PassWallet (.pkpass) file (not the only use case). When I click on any link on this Website I want to check whether it is an other Website or a .pkpass file or whatever.

我也遇到了类似的问题,我想检查在我的 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;

如果我对您的问题的理解正确,您需要一种方法来检查在您的 WebView 中单击的 URL,然后根据该 URL 决定是继续还是停止并执行其他操作。我在我们的应用程序中处理它的方式上面的解决方案。

查看以下链接:

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

关于javascript - React-native android WebView 在加载前处理点击的 Url,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38999499/

相关文章:

javascript - 企业级 wifi 网络 javascript 或 jquery 编码

javascript - 使用箭头键旋转 Canvas 形状

android - Xamarin Android 存档失败

java - 在 ImageView 上绘图

android - ADB over WiFi 连接在连接的 USB 上丢失

javascript - 如何使用正则表达式验证域名?

javascript - Grunt useminPrepare 和 usemin 不能处理多个任务和文件(concat 失败)

Reactjs - 在 api 调用失败时注销/重定向用户

javascript - react native : Disabling scene transitions in NavigationExperimental

reactjs - setState 为对象内的数组