summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.iOS/Renderers/ScrollViewRenderer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Platform.iOS/Renderers/ScrollViewRenderer.cs')
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/ScrollViewRenderer.cs246
1 files changed, 246 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/ScrollViewRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/ScrollViewRenderer.cs
new file mode 100644
index 00000000..1e8ea1fc
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/ScrollViewRenderer.cs
@@ -0,0 +1,246 @@
+using System;
+using System.ComponentModel;
+using System.Drawing;
+#if __UNIFIED__
+using UIKit;
+using Foundation;
+using ObjCRuntime;
+using PointF = CoreGraphics.CGPoint;
+using RectangleF = CoreGraphics.CGRect;
+
+#else
+using MonoTouch.Foundation;
+using MonoTouch.ObjCRuntime;
+using MonoTouch.UIKit;
+using nfloat=System.Single;
+
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class ScrollViewRenderer : UIScrollView, IVisualElementRenderer
+ {
+ EventTracker _events;
+ KeyboardInsetTracker _insetTracker;
+
+ VisualElementPackager _packager;
+
+ RectangleF _previousFrame;
+ ScrollToRequestedEventArgs _requestedScroll;
+ VisualElementTracker _tracker;
+
+ public ScrollViewRenderer() : base(RectangleF.Empty)
+ {
+ ScrollAnimationEnded += HandleScrollAnimationEnded;
+ Scrolled += HandleScrolled;
+ }
+
+ protected IScrollViewController Controller
+ {
+ get { return (IScrollViewController)Element; }
+ }
+
+ ScrollView ScrollView
+ {
+ get { return Element as ScrollView; }
+ }
+
+ 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 UIView NativeView
+ {
+ get { return this; }
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ _requestedScroll = null;
+ var oldElement = Element;
+ Element = element;
+
+ if (oldElement != null)
+ {
+ oldElement.PropertyChanged -= HandlePropertyChanged;
+ ((IScrollViewController)oldElement).ScrollToRequested -= OnScrollToRequested;
+ }
+
+ if (element != null)
+ {
+ element.PropertyChanged += HandlePropertyChanged;
+ ((IScrollViewController)element).ScrollToRequested += OnScrollToRequested;
+ if (_packager == null)
+ {
+ DelaysContentTouches = true;
+
+ _packager = new VisualElementPackager(this);
+ _packager.Load();
+
+ _tracker = new VisualElementTracker(this);
+ _tracker.NativeControlUpdated += OnNativeControlUpdated;
+ _events = new EventTracker(this);
+ _events.LoadEvents(this);
+
+ _insetTracker = new KeyboardInsetTracker(this, () => Window, insets => ContentInset = ScrollIndicatorInsets = insets, point =>
+ {
+ var offset = ContentOffset;
+ offset.Y += point.Y;
+ SetContentOffset(offset, true);
+ });
+ }
+
+ UpdateContentSize();
+ UpdateBackgroundColor();
+
+ OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
+
+ if (element != null)
+ element.SendViewInitialized(this);
+
+ if (!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 UIViewController ViewController
+ {
+ get { return null; }
+ }
+
+ public override void LayoutSubviews()
+ {
+ base.LayoutSubviews();
+
+ if (_requestedScroll != null && Superview != null)
+ {
+ var request = _requestedScroll;
+ _requestedScroll = null;
+ OnScrollToRequested(this, request);
+ }
+
+ if (_previousFrame != Frame)
+ {
+ _previousFrame = Frame;
+ _insetTracker?.UpdateInsets();
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (_packager == null)
+ return;
+
+ SetElement(null);
+
+ _packager.Dispose();
+ _packager = null;
+
+ _tracker.NativeControlUpdated -= OnNativeControlUpdated;
+ _tracker.Dispose();
+ _tracker = null;
+
+ _events.Dispose();
+ _events = null;
+
+ _insetTracker.Dispose();
+ _insetTracker = null;
+
+ ScrollAnimationEnded -= HandleScrollAnimationEnded;
+ Scrolled -= HandleScrolled;
+ }
+
+ 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 == ScrollView.ContentSizeProperty.PropertyName)
+ UpdateContentSize();
+ else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ UpdateBackgroundColor();
+ }
+
+ void HandleScrollAnimationEnded(object sender, EventArgs e)
+ {
+ Controller.SendScrollFinished();
+ }
+
+ void HandleScrolled(object sender, EventArgs e)
+ {
+ UpdateScrollPosition();
+ }
+
+ void OnNativeControlUpdated(object sender, EventArgs eventArgs)
+ {
+ ContentSize = Bounds.Size;
+ UpdateContentSize();
+ }
+
+ void OnScrollToRequested(object sender, ScrollToRequestedEventArgs e)
+ {
+ if (Superview == null)
+ {
+ _requestedScroll = e;
+ return;
+ }
+ if (e.Mode == ScrollToMode.Position)
+ SetContentOffset(new PointF((nfloat)e.ScrollX, (nfloat)e.ScrollY), e.ShouldAnimate);
+ else
+ {
+ var positionOnScroll = Controller.GetScrollPositionForElement(e.Element as VisualElement, e.Position);
+ switch (ScrollView.Orientation)
+ {
+ case ScrollOrientation.Horizontal:
+ SetContentOffset(new PointF((nfloat)positionOnScroll.X, ContentOffset.Y), e.ShouldAnimate);
+ break;
+ case ScrollOrientation.Vertical:
+ SetContentOffset(new PointF(ContentOffset.X, (nfloat)positionOnScroll.Y), e.ShouldAnimate);
+ break;
+ case ScrollOrientation.Both:
+ SetContentOffset(new PointF((nfloat)positionOnScroll.X, (nfloat)positionOnScroll.Y), e.ShouldAnimate);
+ break;
+ }
+ }
+ if (!e.ShouldAnimate)
+ Controller.SendScrollFinished();
+ }
+
+ void UpdateBackgroundColor()
+ {
+ BackgroundColor = Element.BackgroundColor.ToUIColor(Color.Transparent);
+ }
+
+ void UpdateContentSize()
+ {
+ var contentSize = ((ScrollView)Element).ContentSize.ToSizeF();
+ if (!contentSize.IsEmpty)
+ ContentSize = contentSize;
+ }
+
+ void UpdateScrollPosition()
+ {
+ if (ScrollView != null)
+ Controller.SetScrolledPosition(ContentOffset.X, ContentOffset.Y);
+ }
+ }
+} \ No newline at end of file