【问题标题】:Implementing Custom Webview in Xamarin Forms在 Xamarin 表单中实现自定义 Webview
【发布时间】:2020-12-14 03:29:33
【问题描述】:

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

问题是在iOS 项目中实现渲染器时,就像Webview 在没有加载CSS 和Javascript 的情况下进行了初始化。因为它只显示HTML 页面,没有任何功能。

经过一番研究,我知道我们必须实现WKWebviewRenderer,并且我们必须在iOS 中加载LoadFileUrl 方法,但我仍然无法在渲染器中捕获url。

任何人都知道如何将以下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, url, 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);

        }
    }
}

更新:

这是我在可移植项目中为 webview 设置源 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;
}

【问题讨论】:

    标签: xamarin xamarin.forms webview xamarin.ios wkwebview


    【解决方案1】:

    您可以修改自定义渲染器的代码,如下所示。

    [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();
    
            }
        }
    }
    

    【讨论】:

    • 现在正在显示一个白页。我在DidFinishNavigation 添加了一个断点,它永远不会被击中。我认为这就像它永远不会完成导航
    • 我将更新问题只是为了向您展示我是如何设置 webview 源的,也许初始化有问题。只是为了给你所有的细节
    • 添加Webview初始化代码
    • 能否分享整个样本,以便我进行测试?
    • 您可以创建一个包含问题的示例。
    【解决方案2】:

    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
            }
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-12
      • 2019-10-13
      • 1970-01-01
      • 2021-06-28
      • 1970-01-01
      • 1970-01-01
      • 2021-09-28
      • 2020-11-03
      相关资源
      最近更新 更多