summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.iOS/Renderers/TabbedRenderer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Platform.iOS/Renderers/TabbedRenderer.cs')
-rw-r--r--Xamarin.Forms.Platform.iOS/Renderers/TabbedRenderer.cs311
1 files changed, 311 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.iOS/Renderers/TabbedRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/TabbedRenderer.cs
new file mode 100644
index 00000000..7e5121fd
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Renderers/TabbedRenderer.cs
@@ -0,0 +1,311 @@
+using System;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using System.Collections.Generic;
+#if __UNIFIED__
+using UIKit;
+#else
+using MonoTouch.UIKit;
+#endif
+#if __UNIFIED__
+using RectangleF = CoreGraphics.CGRect;
+using SizeF = CoreGraphics.CGSize;
+using PointF = CoreGraphics.CGPoint;
+
+#else
+using nfloat=System.Single;
+using nint=System.Int32;
+using nuint=System.UInt32;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class TabbedRenderer : UITabBarController, IVisualElementRenderer
+ {
+ bool _loaded;
+ Size _queuedSize;
+
+ public override UIViewController SelectedViewController
+ {
+ get { return base.SelectedViewController; }
+ set
+ {
+ base.SelectedViewController = value;
+ UpdateCurrentPage();
+ }
+ }
+
+ protected TabbedPage Tabbed
+ {
+ get { return (TabbedPage)Element; }
+ }
+
+ public VisualElement Element { get; private set; }
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ public SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ return NativeView.GetSizeRequest(widthConstraint, heightConstraint);
+ }
+
+ public UIView NativeView
+ {
+ get { return View; }
+ }
+
+ public void SetElement(VisualElement element)
+ {
+ var oldElement = Element;
+ Element = element;
+
+ FinishedCustomizingViewControllers += HandleFinishedCustomizingViewControllers;
+ Tabbed.PropertyChanged += OnPropertyChanged;
+ Tabbed.PagesChanged += OnPagesChanged;
+
+ OnElementChanged(new VisualElementChangedEventArgs(oldElement, element));
+
+ OnPagesChanged(null, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+
+ if (element != null)
+ element.SendViewInitialized(NativeView);
+
+ //disable edit/reorder of tabs
+ CustomizableViewControllers = null;
+ }
+
+ public void SetElementSize(Size size)
+ {
+ if (_loaded)
+ Element.Layout(new Rectangle(Element.X, Element.Y, size.Width, size.Height));
+ else
+ _queuedSize = size;
+ }
+
+ public UIViewController ViewController
+ {
+ get { return this; }
+ }
+
+ public override void DidRotate(UIInterfaceOrientation fromInterfaceOrientation)
+ {
+ base.DidRotate(fromInterfaceOrientation);
+
+ View.SetNeedsLayout();
+ }
+
+ public override void ViewDidAppear(bool animated)
+ {
+ ((TabbedPage)Element).SendAppearing();
+ base.ViewDidAppear(animated);
+ }
+
+ public override void ViewDidDisappear(bool animated)
+ {
+ base.ViewDidDisappear(animated);
+ ((TabbedPage)Element).SendDisappearing();
+ }
+
+ public override void ViewDidLayoutSubviews()
+ {
+ base.ViewDidLayoutSubviews();
+
+ if (Element == null)
+ return;
+
+ if (!Element.Bounds.IsEmpty)
+ {
+ View.Frame = new System.Drawing.RectangleF((float)Element.X, (float)Element.Y, (float)Element.Width, (float)Element.Height);
+ }
+
+ var frame = View.Frame;
+ var tabBarFrame = TabBar.Frame;
+ ((TabbedPage)Element).ContainerArea = new Rectangle(0, 0, frame.Width, frame.Height - tabBarFrame.Height);
+
+ if (!_queuedSize.IsZero)
+ {
+ Element.Layout(new Rectangle(Element.X, Element.Y, _queuedSize.Width, _queuedSize.Height));
+ _queuedSize = Size.Zero;
+ }
+
+ _loaded = true;
+ }
+
+ public override void ViewDidLoad()
+ {
+ base.ViewDidLoad();
+
+ if (!Forms.IsiOS7OrNewer)
+ WantsFullScreenLayout = false;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ ((TabbedPage)Element).SendDisappearing();
+ Tabbed.PropertyChanged -= OnPropertyChanged;
+ Tabbed.PagesChanged -= OnPagesChanged;
+ FinishedCustomizingViewControllers -= HandleFinishedCustomizingViewControllers;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected virtual void OnElementChanged(VisualElementChangedEventArgs e)
+ {
+ var changed = ElementChanged;
+ if (changed != null)
+ changed(this, e);
+ }
+
+ UIViewController GetViewController(Page page)
+ {
+ var renderer = Platform.GetRenderer(page);
+ if (renderer == null)
+ return null;
+
+ return renderer.ViewController;
+ }
+
+ void HandleFinishedCustomizingViewControllers(object sender, UITabBarCustomizeChangeEventArgs e)
+ {
+ if (e.Changed)
+ UpdateChildrenOrderIndex(e.ViewControllers);
+ }
+
+ void OnPagePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Page.TitleProperty.PropertyName)
+ {
+ var page = (Page)sender;
+ var renderer = Platform.GetRenderer(page);
+ if (renderer == null)
+ return;
+
+ if (renderer.ViewController.TabBarItem != null)
+ renderer.ViewController.TabBarItem.Title = page.Title;
+ }
+ else if (e.PropertyName == Page.IconProperty.PropertyName)
+ {
+ var page = (Page)sender;
+
+ var renderer = Platform.GetRenderer(page);
+ if (renderer == null)
+ return;
+
+ if (renderer.ViewController.TabBarItem == null)
+ return;
+
+ UIImage image = null;
+ if (!string.IsNullOrEmpty(page.Icon))
+ image = new UIImage(page.Icon);
+
+ // the new UITabBarItem forces redraw, setting the UITabBarItem.Image does not
+ renderer.ViewController.TabBarItem = new UITabBarItem(page.Title, image, 0);
+
+ if (image != null)
+ image.Dispose();
+ }
+ }
+
+ void OnPagesChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ e.Apply((o, i, c) => SetupPage((Page)o, i), (o, i) => TeardownPage((Page)o, i), Reset);
+
+ SetControllers();
+
+ UIViewController controller = null;
+ if (Tabbed.CurrentPage != null)
+ controller = GetViewController(Tabbed.CurrentPage);
+ if (controller != null && controller != base.SelectedViewController)
+ base.SelectedViewController = controller;
+ }
+
+ void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "CurrentPage")
+ {
+ var current = Tabbed.CurrentPage;
+ if (current == null)
+ return;
+
+ var controller = GetViewController(current);
+ if (controller == null)
+ return;
+
+ SelectedViewController = controller;
+ }
+ }
+
+ void Reset()
+ {
+ var i = 0;
+ foreach (var page in Tabbed.Children)
+ SetupPage(page, i++);
+ }
+
+ void SetControllers()
+ {
+ var list = new List<UIViewController>();
+ for (var i = 0; i < Element.LogicalChildren.Count; i++)
+ {
+ var child = Element.LogicalChildren[i];
+ var v = child as VisualElement;
+ if (v == null)
+ continue;
+ if (Platform.GetRenderer(v) != null)
+ list.Add(Platform.GetRenderer(v).ViewController);
+ }
+ ViewControllers = list.ToArray();
+ }
+
+ void SetupPage(Page page, int index)
+ {
+ var renderer = Platform.GetRenderer(page);
+ if (renderer == null)
+ {
+ renderer = Platform.CreateRenderer(page);
+ Platform.SetRenderer(page, renderer);
+ }
+
+ page.PropertyChanged += OnPagePropertyChanged;
+
+ UIImage icon = null;
+ if (page.Icon != null)
+ icon = new UIImage(page.Icon);
+
+ renderer.ViewController.TabBarItem = new UITabBarItem(page.Title, icon, 0);
+ if (icon != null)
+ icon.Dispose();
+
+ renderer.ViewController.TabBarItem.Tag = index;
+ }
+
+ void TeardownPage(Page page, int index)
+ {
+ page.PropertyChanged -= OnPagePropertyChanged;
+
+ Platform.SetRenderer(page, null);
+ }
+
+ void UpdateChildrenOrderIndex(UIViewController[] viewControllers)
+ {
+ for (var i = 0; i < viewControllers.Length; i++)
+ {
+ var originalIndex = -1;
+ if (int.TryParse(viewControllers[i].TabBarItem.Tag.ToString(), out originalIndex))
+ {
+ var page = (Page)Tabbed.InternalChildren[originalIndex];
+ TabbedPage.SetIndex(page, i);
+ }
+ }
+ }
+
+ void UpdateCurrentPage()
+ {
+ ((TabbedPage)Element).CurrentPage = SelectedIndex >= 0 && SelectedIndex < Tabbed.InternalChildren.Count ? Tabbed.GetPageByIndex((int)SelectedIndex) : null;
+ }
+ }
+} \ No newline at end of file