在Xamarin表单中实现自定义Webview

问题描述

我是Xamarin.Forms的新手,并且已经在Droid项目中实现了自定义Web视图渲染器。

问题是在iOS项目中实现渲染器时,就像Webview初始化时未加载CSS和Javascript。因为它仅显示HTML页,但没有任何功能

经过研究,我知道我们必须实现WKWebvieWrenderer,并且必须在LoadFileUrl中加载iOS方法,但是我仍然无法在渲染器中捕获该URL。 / p>

任何人都对如何将以下Android Renderer代码实现到iOS Renderer中有想法??

Droid项目中的自定义渲染器:

[assembly: ExportRenderer(typeof(Xamarin.Forms.WebView),typeof(MyProject.Droid.WebVieWrenderer))]
namespace MyProject.Droid
{
    public class WebVieWrenderer : Xamarin.Forms.Platform.Android.WebVieWrenderer
    {
        private bool isMyCustomWebview = false;
        public IWebViewController ElementController => Element;

        protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Xamarin.Forms.WebView> e)
        {
            base.OnElementChanged(e);
            if (e.NewElement.GetType() == typeof(MyCustomWebview))
            {
                Control.SetWebViewClient(new Callback(this));
                isMyCustomWebview = true;
            }
            else
            {
                Control.SetWebViewClient(new Callback(Plugin.CurrentActivity.CrossCurrentActivity.Current.Activity));
                isMyCustomWebview = false;
            }
        }


        public class Callback : WebViewClient
        {
            Activity _context;
            public Callback(Activity _context)
            {
                this._context = _context;
            }

            WebVieWrenderer _renderer;

            public Callback(WebVieWrenderer renderer)
            {
                _renderer = renderer ?? throw new ArgumentNullException("Renderer");
            }

            public override void OnPageStarted(Android.Webkit.WebView view,string url,Android.Graphics.Bitmap favicon)
            {
                base.OnPageStarted(view,url,favicon);
                if (_renderer != null && _renderer.isMyCustomWebview)
                {
                    DependencyService.Get<ILoadingIndicator>().Show();
                    var args = new WebNavigatingEventArgs(WebNavigationEvent.NewPage,new UrlWebViewSource { Url = url },url);
                    _renderer.ElementController.SendNavigating(args);
                }

            }
            public override void OnPageFinished(Android.Webkit.WebView view,string url)
            {
                base.OnPageFinished(view,url);
                if (_renderer != null && _renderer.isMyCustomWebview)
                {
                    DependencyService.Get<ILoadingIndicator>().dismiss();
                    var source = new UrlWebViewSource { Url = url };
                    var args = new WebNavigatedEventArgs(WebNavigationEvent.NewPage,source,WebNavigationResult.Success);
                    _renderer.ElementController.SendNavigated(args);
                }
            }
        }
    }
}

更新:iOS项目中的自定义渲染器:

[assembly: ExportRenderer(typeof(Xamarin.Forms.WebView),typeof(MyProject.iOS.WebVieWrenderer))]
namespace MyProject.iOS
{
    // Xamarin.Forms.Platform.iOS.WebVieWrenderer
    public class WebVieWrenderer : VieWrenderer<WebView,WKWebView>
    {
        WKWebView wkWebView;

        protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
        {
            base.OnElementChanged(e);
            if (Control != null) return;
            var config = new WKWebViewConfiguration();
            wkWebView = new WKWebView(Frame,config) { NavigationDelegate = new MyNavigationDelegate() };
            SetNativeControl(wkWebView);
        }
    }

    public class MyNavigationDelegate : WKNavigationDelegate
    {
        public override void DidFinishNavigation(WKWebView webView,WKNavigation navigation)
        {

            //get url here
            var url = webView.Url;

            // webView.LoadFileUrl(url,url);

        }
    }
}

更新:

这是我在可移植项目中为Web视图设置源URL和基础URL的方法

var result = await client.PostAsync("/embedded/pay",content);
if (result.IsSuccessstatusCode)
{
    var resp = await result.Content.ReadAsstringAsync();
    var html = new HtmlWebViewSource
    {
        Html = resp,BaseUrl = paymentGatewayUrl
    };

    //Adding Cookie
    CookieContainer cookies = new CookieContainer();
    var domain = new Uri(html.BaseUrl).Host;
    var cookie = new Cookie
    {
        Secure = true,Expired = false,HttpOnly = false,Name = "cookie",Expires = DateTime.Now.AddDays(10),Domain = domain,Path = "/"
    };
    cookies.Add(new Uri(html.BaseUrl),cookie);
    webView.source = html;
}

解决方法

您可以按照以下步骤修改自定义渲染器的代码。

[assembly: ExportRenderer(typeof(WebView),typeof(MyWebViewRenderer))]
namespace xxx.iOS
{

    public class MyWebViewRenderer : ViewRenderer<WebView,WKWebView>
    {
        WKWebView wkWebView;

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

            if (Control != null) return;
            var config = new WKWebViewConfiguration();
            wkWebView = new WKWebView(Frame,config) { NavigationDelegate = new MyNavigationDelegate() };
            SetNativeControl(wkWebView);
        }
    }

    public class MyNavigationDelegate : WKNavigationDelegate
    {
        public override void DidFinishNavigation(WKWebView webView,WKNavigation navigation)
        {

            //get url here
            var url = webView.Url;

            //webView.LoadFileUrl();

        }
    }
}
,

iOS渲染器:

using WebKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(WebView),typeof(MyNamespace.iOS.MyWebViewRenderer))]
namespace MyNamespace.iOS
{
  //WkWebViewRenderer inherits from WKWebView
  public class MyWebViewRenderer : WkWebViewRenderer
  {
    protected override void OnElementChanged(VisualElementChangedEventArgs e)
    {
        base.OnElementChanged(e);

        if (e.NewElement != null)
        {
            WKWebView wkWebView = this;
            wkWebView.NavigationDelegate = new MyNavigationDelegate(); //not shown here
        }
    }
  }
}