听WkWebView的导航事件

时间:2016-04-05 20:17:51

标签: ios xamarin

我是Xamarin和iOS的新手。我试图在Xamarin Forms中创建一个呈现WkWebView的自定义渲染器。我希望当用户点击网页浏览中的链接时调用我的DidStartProvisionalNavigation()方法,但这种方法没有发生,我也不知道为什么。我尝试使用Xlab' HybridViewRender作为参考。有人能告诉我当用户点击链接时如何让WkWebView调用DidStartProvisionalNavigation()吗?感谢

这是我使用WkWebView的自定义IOS渲染器的源代码。

public class HybridWebViewRenderer : ViewRenderer<HybridWebView, WKWebView>, IWKScriptMessageHandler
    {
        const string JavaScriptFunction = "function invokeCSharpAction(data){window.webkit.messageHandlers.invokeAction.postMessage(data);}";
        WKUserContentController userController;

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if (e.PropertyName == "Uri") 
                Control.LoadRequest (new NSUrlRequest (new NSUrl (Element.Uri)));
        }

        protected override void OnElementChanged (ElementChangedEventArgs<HybridWebView> e)
        {
            base.OnElementChanged (e);

            if (Control == null) {
                userController = new WKUserContentController ();
                var script = new WKUserScript (new NSString (JavaScriptFunction), WKUserScriptInjectionTime.AtDocumentEnd, false);
                userController.AddUserScript (script);
                userController.AddScriptMessageHandler (this, "invokeAction");
                var config = new WKWebViewConfiguration { UserContentController = userController };
                config.ApplicationNameForUserAgent += " MethodApp";
                var webView = new WKWebView (Frame, config);

                SetNativeControl (webView);
            }
            if (e.OldElement != null) {
                userController.RemoveAllUserScripts ();
                userController.RemoveScriptMessageHandler ("invokeAction");
                var hybridWebView = e.OldElement as HybridWebView;
                e.OldElement.onRefresh -= Refresh;
                hybridWebView.Cleanup ();
            }
            if (e.NewElement != null) {
                e.NewElement.onRefresh += Refresh;
                //string fileName = Path.Combine (NSBundle.MainBundle.BundlePath, string.Format ("Content/{0}", Element.Uri));
                if (Element.Uri != null) 
                    Control.LoadRequest (new NSUrlRequest (new NSUrl (Element.Uri)));

            }
        }

        public void Refresh(object sender, EventArgs ea) {
            Control.Reload();
        }

        public void DidReceiveScriptMessage (WKUserContentController userContentController, WKScriptMessage message)
        {
            Element.InvokeAction (message.Body.ToString ());
        }

        [Export("webView:didStartProvisionalNavigation:")]
        public void DidStartProvisionalNavigation(WKWebView webView, WKNavigation navigation)
        {
            Element.OnNavigating(webView.Url);
        }
    }

4 个答案:

答案 0 :(得分:3)

您只需要添加以下行:

webView.NavigationDelegate = this; 

代码之后:

var webView = new WKWebView (Frame, config);

也不要忘记改变:

public class HybridWebViewRenderer : ViewRenderer< HybridWebView,WKWebView>, IWKScriptMessageHandler, IWKNavigationDelegate

之后,您可以使用和覆盖DidStartProvisionalNavigation代码:

[Export("webView:didStartProvisionalNavigation:")]
public void DidStartProvisionalNavigation(WKWebView webView,WKNavigation navigation)
{
// When navigation starts, this gets called
Console.WriteLine("DidStartProvisionalNavigation");
}

答案 1 :(得分:2)

DidStartProvisionalNavigation方法包含在IWKNavigationDelegate中,WKWebView包含属性NavigationDelegate

您需要的只是一个自定义代表

public class MyNavigationDelegate : WKNavigationDelegate
{
    private readonly HybridWebViewRenderer _renderer;

    public MyNavigationDelegate(HybridWebViewRenderer  renderer)
    {
        _renderer = renderer;
    }

    public override void DidFailProvisionalNavigation(WKWebView webView, WKNavigation navigation, NSError error)
    {
        // call methods of your renderer or its properties like
        _renderer.Element.OnNavigating(webView.Url);
    }
}

在您的渲染器中的webview上设置为NavigationDelegate

var webView = new WKWebView (Frame, config);
webView.NavigationDelegate = new MyNavigationDelegate(this); 

答案 2 :(得分:1)

我相信

public override void DidStartProvisionalNavigation( WKWebView webView, WKNavigation navigation )

需要位于实现WKNavigationDelegate的委托类中,然后将其分配给webview的NavigationDelegate属性。

此论坛thread提供了有关使用WKWebView

的更多信息

答案 3 :(得分:1)

我没有看到你为WKWebView设置了WeakNavigationDelegate。 XLabs的混合渲染器在这里做到了:

var webView = new WKWebView(Frame, config) { WeakNavigationDelegate = this };

https://github.com/XLabs/Xamarin-Forms-Labs/blob/master/src/Forms/XLabs.Forms.iOS/Controls/HybridWebView/HybridWebViewRenderer.cs#L133