【问题标题】:Listening to WkWebView's navigate event监听 WkWebView 的导航事件
【发布时间】:2016-07-20 00:50:25
【问题描述】:

我是 Xamarin 和 iOS 的新手。我正在尝试在呈现 WkWebView 的 Xamarin Forms 中创建自定义渲染器。我希望当用户点击 web 视图中的链接时调用我的 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);
        }
    }

【问题讨论】:

    标签: ios xamarin


    【解决方案1】:

    你只需要添加这一行:

    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");
    }
    

    【讨论】:

      【解决方案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); 
      

      【讨论】:

        【解决方案3】:

        我相信

        public override void DidStartProvisionalNavigation( WKWebView webView, WKNavigation navigation )
        

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

        这个论坛thread 有更多关于使用 WKWebView 的信息

        【讨论】:

          【解决方案4】:

          我没有看到您为 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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-12-27
            • 1970-01-01
            • 2022-11-04
            • 1970-01-01
            • 1970-01-01
            • 2016-02-10
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多