Implementieren einer benutzerdefinierten Webansicht in Xamarin Forms

Aug 25 2020

Ich bin neu in Xamarin.Formsund habe einen benutzerdefinierten Web View Renderer im DroidProjekt implementiert .

Das Problem ist, dass beim Implementieren des Renderers im iOSProjekt der Renderer Webviewohne Laden von CSS und Javascript initialisiert wird. Weil nur HTMLSeiten ohne Funktionalität angezeigt werden.

Nach einigen Recherchen weiß ich, dass wir WKWebviewRendererdie LoadFileUrlMethode implementieren und laden müssen, iOSaber ich kann die URL im Renderer immer noch nicht abfangen.

Hat jemand eine Idee bitte, wie man den folgenden Android RendererCode in iOS Renderer?? implementiert ?

Benutzerdefinierter Renderer im Droid-Projekt:

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

UPDATE: Benutzerdefinierter Renderer im iOS-Projekt:

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

        }
    }
}

AKTUALISIEREN:

So lege ich die Quell- und Basis-URL für die Webansicht im portablen Projekt fest:

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

Antworten

1 LucasZhang-MSFT Aug 25 2020 at 13:12

Sie können den Code von Custom Renderer wie folgt ändern .

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

        }
    }
}
Benl Aug 26 2020 at 09:13

iOS-Renderer:

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