diff options
Diffstat (limited to 'Xamarin.Forms.Platform.Android/Renderers/WebViewRenderer.cs')
-rw-r--r-- | Xamarin.Forms.Platform.Android/Renderers/WebViewRenderer.cs | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.Android/Renderers/WebViewRenderer.cs b/Xamarin.Forms.Platform.Android/Renderers/WebViewRenderer.cs new file mode 100644 index 00000000..d2c0f0d6 --- /dev/null +++ b/Xamarin.Forms.Platform.Android/Renderers/WebViewRenderer.cs @@ -0,0 +1,206 @@ +using System; +using System.ComponentModel; +using Android.Webkit; +using AWebView = Android.Webkit.WebView; + +namespace Xamarin.Forms.Platform.Android +{ + public class WebViewRenderer : ViewRenderer<WebView, AWebView>, IWebViewRenderer + { + bool _ignoreSourceChanges; + FormsWebChromeClient _webChromeClient; + + public WebViewRenderer() + { + AutoPackage = false; + } + + public void LoadHtml(string html, string baseUrl) + { + Control.LoadDataWithBaseURL(baseUrl == null ? "file:///android_asset/" : baseUrl, html, "text/html", "UTF-8", null); + } + + public void LoadUrl(string url) + { + Control.LoadUrl(url); + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (Element != null) + { + if (Control != null) + Control.StopLoading(); + Element.EvalRequested -= OnEvalRequested; + Element.GoBackRequested -= OnGoBackRequested; + Element.GoForwardRequested -= OnGoForwardRequested; + + _webChromeClient?.Dispose(); + } + } + + base.Dispose(disposing); + } + + protected virtual FormsWebChromeClient GetFormsWebChromeClient() + { + return new FormsWebChromeClient(); + } + + protected override Size MinimumSize() + { + return new Size(Context.ToPixels(40), Context.ToPixels(40)); + } + + protected override void OnElementChanged(ElementChangedEventArgs<WebView> e) + { + base.OnElementChanged(e); + + if (Control == null) + { + var webView = new AWebView(Context); + webView.LayoutParameters = new global::Android.Widget.AbsoluteLayout.LayoutParams(LayoutParams.MatchParent, LayoutParams.MatchParent, 0, 0); + webView.SetWebViewClient(new WebClient(this)); + + _webChromeClient = GetFormsWebChromeClient(); + _webChromeClient.SetContext(Context as IStartActivityForResult); + webView.SetWebChromeClient(_webChromeClient); + + webView.Settings.JavaScriptEnabled = true; + webView.Settings.DomStorageEnabled = true; + SetNativeControl(webView); + } + + if (e.OldElement != null) + { + e.OldElement.EvalRequested -= OnEvalRequested; + e.OldElement.GoBackRequested -= OnGoBackRequested; + e.OldElement.GoForwardRequested -= OnGoForwardRequested; + } + + if (e.NewElement != null) + { + e.NewElement.EvalRequested += OnEvalRequested; + e.NewElement.GoBackRequested += OnGoBackRequested; + e.NewElement.GoForwardRequested += OnGoForwardRequested; + } + + Load(); + } + + protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) + { + base.OnElementPropertyChanged(sender, e); + + switch (e.PropertyName) + { + case "Source": + Load(); + break; + } + } + + void Load() + { + if (_ignoreSourceChanges) + return; + + if (Element.Source != null) + Element.Source.Load(this); + + UpdateCanGoBackForward(); + } + + void OnEvalRequested(object sender, EventArg<string> eventArg) + { + LoadUrl("javascript:" + eventArg.Data); + } + + void OnGoBackRequested(object sender, EventArgs eventArgs) + { + if (Control.CanGoBack()) + Control.GoBack(); + + UpdateCanGoBackForward(); + } + + void OnGoForwardRequested(object sender, EventArgs eventArgs) + { + if (Control.CanGoForward()) + Control.GoForward(); + + UpdateCanGoBackForward(); + } + + void UpdateCanGoBackForward() + { + if (Element == null || Control == null) + return; + Element.CanGoBack = Control.CanGoBack(); + Element.CanGoForward = Control.CanGoForward(); + } + + class WebClient : WebViewClient + { + WebNavigationResult _navigationResult = WebNavigationResult.Success; + WebViewRenderer _renderer; + + public WebClient(WebViewRenderer renderer) + { + if (renderer == null) + throw new ArgumentNullException("renderer"); + _renderer = renderer; + } + + public override void OnPageFinished(AWebView view, string url) + { + if (_renderer.Element == null || url == "file:///android_asset/") + return; + + var source = new UrlWebViewSource { Url = url }; + _renderer._ignoreSourceChanges = true; + ((IElementController)_renderer.Element).SetValueFromRenderer(WebView.SourceProperty, source); + _renderer._ignoreSourceChanges = false; + + var args = new WebNavigatedEventArgs(WebNavigationEvent.NewPage, source, url, _navigationResult); + + _renderer.Element.SendNavigated(args); + + _renderer.UpdateCanGoBackForward(); + + base.OnPageFinished(view, url); + } + + public override void OnReceivedError(AWebView view, ClientError errorCode, string description, string failingUrl) + { + _navigationResult = WebNavigationResult.Failure; + if (errorCode == ClientError.Timeout) + _navigationResult = WebNavigationResult.Timeout; + base.OnReceivedError(view, errorCode, description, failingUrl); + } + + public override bool ShouldOverrideUrlLoading(AWebView view, string url) + { + if (_renderer.Element == null) + return true; + + var args = new WebNavigatingEventArgs(WebNavigationEvent.NewPage, new UrlWebViewSource { Url = url }, url); + + _renderer.Element.SendNavigating(args); + _navigationResult = WebNavigationResult.Success; + + _renderer.UpdateCanGoBackForward(); + return args.Cancel; + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (disposing) + _renderer = null; + } + } + } +}
\ No newline at end of file |