diff options
author | Jason Smith <jason.smith@xamarin.com> | 2016-03-22 13:02:25 -0700 |
---|---|---|
committer | Jason Smith <jason.smith@xamarin.com> | 2016-03-22 16:13:41 -0700 |
commit | 17fdde66d94155fc62a034fa6658995bef6fd6e5 (patch) | |
tree | b5e5073a2a7b15cdbe826faa5c763e270a505729 /Xamarin.Forms.Platform.iOS/Renderers/WebViewRenderer.cs | |
download | xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.tar.gz xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.tar.bz2 xamarin-forms-17fdde66d94155fc62a034fa6658995bef6fd6e5.zip |
Initial import
Diffstat (limited to 'Xamarin.Forms.Platform.iOS/Renderers/WebViewRenderer.cs')
-rw-r--r-- | Xamarin.Forms.Platform.iOS/Renderers/WebViewRenderer.cs | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/WebViewRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/WebViewRenderer.cs new file mode 100644 index 00000000..538bc2d0 --- /dev/null +++ b/Xamarin.Forms.Platform.iOS/Renderers/WebViewRenderer.cs @@ -0,0 +1,270 @@ +using System; +using System.Drawing; +using System.ComponentModel; +#if __UNIFIED__ +using UIKit; +using Foundation; + +#else +using MonoTouch.UIKit; +using MonoTouch.Foundation; +#endif + +namespace Xamarin.Forms.Platform.iOS +{ + public class WebViewRenderer : UIWebView, IVisualElementRenderer, IWebViewRenderer + { + EventTracker _events; + bool _ignoreSourceChanges; + WebNavigationEvent _lastBackForwardEvent; + VisualElementPackager _packager; + + VisualElementTracker _tracker; + + public WebViewRenderer() : base(RectangleF.Empty) + { + } + + public VisualElement Element { get; private set; } + + public event EventHandler<VisualElementChangedEventArgs> ElementChanged; + + public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint) + { + return NativeView.GetSizeRequest(widthConstraint, heightConstraint, 44, 44); + } + + public void SetElement(VisualElement element) + { + var oldElement = Element; + Element = element; + Element.PropertyChanged += HandlePropertyChanged; + ((WebView)Element).EvalRequested += OnEvalRequested; + ((WebView)Element).GoBackRequested += OnGoBackRequested; + ((WebView)Element).GoForwardRequested += OnGoForwardRequested; + Delegate = new CustomWebViewDelegate(this); + + BackgroundColor = UIColor.Clear; + + AutosizesSubviews = true; + AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight; + + _tracker = new VisualElementTracker(this); + + _packager = new VisualElementPackager(this); + _packager.Load(); + + _events = new EventTracker(this); + _events.LoadEvents(this); + + Load(); + + OnElementChanged(new VisualElementChangedEventArgs(oldElement, element)); + + if (Element != null && !string.IsNullOrEmpty(Element.AutomationId)) + AccessibilityIdentifier = Element.AutomationId; + + if (element != null) + element.SendViewInitialized(this); + + if (Element != null && !string.IsNullOrEmpty(Element.AutomationId)) + AccessibilityIdentifier = Element.AutomationId; + } + + public void SetElementSize(Size size) + { + Layout.LayoutChildIntoBoundingRegion(Element, new Rectangle(Element.X, Element.Y, size.Width, size.Height)); + } + + public void LoadHtml(string html, string baseUrl) + { + if (html != null) + LoadHtmlString(html, baseUrl == null ? new NSUrl(NSBundle.MainBundle.BundlePath, true) : new NSUrl(baseUrl, true)); + } + + public void LoadUrl(string url) + { + LoadRequest(new NSUrlRequest(new NSUrl(url))); + } + + public override void LayoutSubviews() + { + base.LayoutSubviews(); + + // ensure that inner scrollview properly resizes when frame of webview updated + ScrollView.Frame = Bounds; + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (IsLoading) + StopLoading(); + + Element.PropertyChanged -= HandlePropertyChanged; + ((WebView)Element).EvalRequested -= OnEvalRequested; + ((WebView)Element).GoBackRequested -= OnGoBackRequested; + ((WebView)Element).GoForwardRequested -= OnGoForwardRequested; + } + + base.Dispose(disposing); + } + + protected virtual void OnElementChanged(VisualElementChangedEventArgs e) + { + var changed = ElementChanged; + if (changed != null) + changed(this, e); + } + + void HandlePropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == WebView.SourceProperty.PropertyName) + Load(); + } + + void Load() + { + if (_ignoreSourceChanges) + return; + + if (((WebView)Element).Source != null) + ((WebView)Element).Source.Load(this); + + UpdateCanGoBackForward(); + } + + void OnEvalRequested(object sender, EventArg<string> eventArg) + { + EvaluateJavascript(eventArg.Data); + } + + void OnGoBackRequested(object sender, EventArgs eventArgs) + { + if (CanGoBack) + { + _lastBackForwardEvent = WebNavigationEvent.Back; + GoBack(); + } + + UpdateCanGoBackForward(); + } + + void OnGoForwardRequested(object sender, EventArgs eventArgs) + { + if (CanGoForward) + { + _lastBackForwardEvent = WebNavigationEvent.Forward; + GoForward(); + } + + UpdateCanGoBackForward(); + } + + void UpdateCanGoBackForward() + { + ((WebView)Element).CanGoBack = CanGoBack; + ((WebView)Element).CanGoForward = CanGoForward; + } + + class CustomWebViewDelegate : UIWebViewDelegate + { + readonly WebViewRenderer _renderer; + WebNavigationEvent _lastEvent; + + public CustomWebViewDelegate(WebViewRenderer renderer) + { + if (renderer == null) + throw new ArgumentNullException("renderer"); + _renderer = renderer; + } + + WebView WebView + { + get { return (WebView)_renderer.Element; } + } + + public override void LoadFailed(UIWebView webView, NSError error) + { + var url = GetCurrentUrl(); + WebView.SendNavigated(new WebNavigatedEventArgs(_lastEvent, new UrlWebViewSource { Url = url }, url, WebNavigationResult.Failure)); + + _renderer.UpdateCanGoBackForward(); + } + + public override void LoadingFinished(UIWebView webView) + { + if (webView.IsLoading) + return; + + _renderer._ignoreSourceChanges = true; + var url = GetCurrentUrl(); + ((IElementController)WebView).SetValueFromRenderer(WebView.SourceProperty, new UrlWebViewSource { Url = url }); + _renderer._ignoreSourceChanges = false; + + var args = new WebNavigatedEventArgs(_lastEvent, WebView.Source, url, WebNavigationResult.Success); + WebView.SendNavigated(args); + + _renderer.UpdateCanGoBackForward(); + } + + public override void LoadStarted(UIWebView webView) + { + } + + public override bool ShouldStartLoad(UIWebView webView, NSUrlRequest request, UIWebViewNavigationType navigationType) + { + var navEvent = WebNavigationEvent.NewPage; + switch (navigationType) + { + case UIWebViewNavigationType.LinkClicked: + navEvent = WebNavigationEvent.NewPage; + break; + case UIWebViewNavigationType.FormSubmitted: + navEvent = WebNavigationEvent.NewPage; + break; + case UIWebViewNavigationType.BackForward: + navEvent = _renderer._lastBackForwardEvent; + break; + case UIWebViewNavigationType.Reload: + navEvent = WebNavigationEvent.Refresh; + break; + case UIWebViewNavigationType.FormResubmitted: + navEvent = WebNavigationEvent.NewPage; + break; + case UIWebViewNavigationType.Other: + navEvent = WebNavigationEvent.NewPage; + break; + } + + _lastEvent = navEvent; + var lastUrl = request.Url.ToString(); + var args = new WebNavigatingEventArgs(navEvent, new UrlWebViewSource { Url = lastUrl }, lastUrl); + + WebView.SendNavigating(args); + _renderer.UpdateCanGoBackForward(); + return !args.Cancel; + } + + string GetCurrentUrl() + { + return _renderer?.Request?.Url?.AbsoluteUrl?.ToString(); + } + } + + #region IPlatformRenderer implementation + + public UIView NativeView + { + get { return this; } + } + + public UIViewController ViewController + { + get { return null; } + } + + #endregion + } +}
\ No newline at end of file |