summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.iOS/Cells
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Platform.iOS/Cells')
-rw-r--r--Xamarin.Forms.Platform.iOS/Cells/CellRenderer.cs77
-rw-r--r--Xamarin.Forms.Platform.iOS/Cells/CellTableViewCell.cs96
-rw-r--r--Xamarin.Forms.Platform.iOS/Cells/EntryCellRenderer.cs186
-rw-r--r--Xamarin.Forms.Platform.iOS/Cells/ImageCellRenderer.cs70
-rw-r--r--Xamarin.Forms.Platform.iOS/Cells/SwitchCellRenderer.cs94
-rw-r--r--Xamarin.Forms.Platform.iOS/Cells/TextCellRenderer.cs73
-rw-r--r--Xamarin.Forms.Platform.iOS/Cells/ViewCellRenderer.cs176
7 files changed, 772 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.iOS/Cells/CellRenderer.cs b/Xamarin.Forms.Platform.iOS/Cells/CellRenderer.cs
new file mode 100644
index 00000000..c01a7774
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Cells/CellRenderer.cs
@@ -0,0 +1,77 @@
+using System;
+#if __UNIFIED__
+using UIKit;
+using Foundation;
+
+#else
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class CellRenderer : IRegisterable
+ {
+ static readonly BindableProperty RealCellProperty = BindableProperty.CreateAttached("RealCell", typeof(UITableViewCell), typeof(Cell), null);
+
+ EventHandler _onForceUpdateSizeRequested;
+
+ public virtual UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
+ {
+ var tvc = reusableCell as CellTableViewCell ?? new CellTableViewCell(UITableViewCellStyle.Default, item.GetType().FullName);
+
+ tvc.Cell = item;
+
+ WireUpForceUpdateSizeRequested(item, tvc, tv);
+
+ tvc.TextLabel.Text = item.ToString();
+
+ UpdateBackground(tvc, item);
+ return tvc;
+ }
+
+ protected void UpdateBackground(UITableViewCell tableViewCell, Cell cell)
+ {
+ if (TemplatedItemsList<ItemsView<Cell>, Cell>.GetIsGroupHeader(cell))
+ {
+ if (UIDevice.CurrentDevice.CheckSystemVersion(7, 0))
+ tableViewCell.BackgroundColor = new UIColor(247f / 255f, 247f / 255f, 247f / 255f, 1);
+ }
+ else
+ {
+ // Must be set to a solid color or blending issues will occur
+ var bgColor = UIColor.White;
+
+ var element = cell.RealParent as VisualElement;
+ if (element != null)
+ bgColor = element.BackgroundColor == Color.Default ? bgColor : element.BackgroundColor.ToUIColor();
+
+ tableViewCell.BackgroundColor = bgColor;
+ }
+ }
+
+ protected void WireUpForceUpdateSizeRequested(Cell cell, UITableViewCell nativeCell, UITableView tableView)
+ {
+ cell.ForceUpdateSizeRequested -= _onForceUpdateSizeRequested;
+
+ _onForceUpdateSizeRequested = delegate
+ {
+ var index = tableView.IndexPathForCell(nativeCell);
+ if (index != null)
+ tableView.ReloadRows(new[] { index }, UITableViewRowAnimation.None);
+ };
+
+ cell.ForceUpdateSizeRequested += _onForceUpdateSizeRequested;
+ }
+
+ internal static UITableViewCell GetRealCell(BindableObject cell)
+ {
+ return (UITableViewCell)cell.GetValue(RealCellProperty);
+ }
+
+ internal static void SetRealCell(BindableObject cell, UITableViewCell renderer)
+ {
+ cell.SetValue(RealCellProperty, renderer);
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Cells/CellTableViewCell.cs b/Xamarin.Forms.Platform.iOS/Cells/CellTableViewCell.cs
new file mode 100644
index 00000000..a9265868
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Cells/CellTableViewCell.cs
@@ -0,0 +1,96 @@
+using System;
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class CellTableViewCell : UITableViewCell, INativeElementView
+ {
+ Cell _cell;
+
+ public Action<object, PropertyChangedEventArgs> PropertyChanged;
+
+ public CellTableViewCell(UITableViewCellStyle style, string key) : base(style, key)
+ {
+ }
+
+ public Cell Cell
+ {
+ get { return _cell; }
+ set
+ {
+ if (_cell == value)
+ return;
+
+ if (_cell != null)
+ Device.BeginInvokeOnMainThread(_cell.SendDisappearing);
+ _cell = value;
+ if (_cell != null)
+ Device.BeginInvokeOnMainThread(_cell.SendAppearing);
+ }
+ }
+
+ public Element Element => Cell;
+
+ public void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (PropertyChanged != null)
+ PropertyChanged(this, e);
+ }
+
+ internal static UITableViewCell GetNativeCell(UITableView tableView, Cell cell, bool recycleCells = false, string templateId = "")
+ {
+ var id = cell.GetType().FullName;
+
+ var renderer = (CellRenderer)Registrar.Registered.GetHandler(cell.GetType());
+
+ ContextActionsCell contextCell = null;
+ UITableViewCell reusableCell = null;
+ if (cell.HasContextActions || recycleCells)
+ {
+ contextCell = (ContextActionsCell)tableView.DequeueReusableCell(ContextActionsCell.Key + templateId);
+ if (contextCell == null)
+ {
+ contextCell = new ContextActionsCell(templateId);
+ reusableCell = tableView.DequeueReusableCell(id);
+ }
+ else
+ {
+ contextCell.Close();
+ reusableCell = contextCell.ContentCell;
+
+ if (reusableCell.ReuseIdentifier.ToString() != id)
+ reusableCell = null;
+ }
+ }
+ else
+ reusableCell = tableView.DequeueReusableCell(id);
+
+ var nativeCell = renderer.GetCell(cell, reusableCell, tableView);
+
+ var cellWithContent = nativeCell;
+
+ // Sometimes iOS for returns a dequeued cell whose Layer is hidden.
+ // This prevents it from showing up, so lets turn it back on!
+ if (cellWithContent.Layer.Hidden)
+ cellWithContent.Layer.Hidden = false;
+
+ if (contextCell != null)
+ {
+ contextCell.Update(tableView, cell, nativeCell);
+ nativeCell = contextCell;
+ }
+
+ // Because the layer was hidden we need to layout the cell by hand
+ if (cellWithContent != null)
+ cellWithContent.LayoutSubviews();
+
+ return nativeCell;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Cells/EntryCellRenderer.cs b/Xamarin.Forms.Platform.iOS/Cells/EntryCellRenderer.cs
new file mode 100644
index 00000000..1af49b4a
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Cells/EntryCellRenderer.cs
@@ -0,0 +1,186 @@
+using System;
+using System.ComponentModel;
+using System.Drawing;
+#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 EntryCellRenderer : CellRenderer
+ {
+ static readonly Color DefaultTextColor = Color.Black;
+
+ public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
+ {
+ var entryCell = (EntryCell)item;
+
+ var tvc = reusableCell as EntryCellTableViewCell;
+ if (tvc == null)
+ tvc = new EntryCellTableViewCell(item.GetType().FullName);
+ else
+ {
+ tvc.Cell.PropertyChanged -= OnCellPropertyChanged;
+ tvc.TextFieldTextChanged -= OnTextFieldTextChanged;
+ tvc.KeyboardDoneButtonPressed -= OnKeyBoardDoneButtonPressed;
+ }
+
+ SetRealCell(item, tvc);
+
+ tvc.Cell = item;
+ tvc.Cell.PropertyChanged += OnCellPropertyChanged;
+ tvc.TextFieldTextChanged += OnTextFieldTextChanged;
+ tvc.KeyboardDoneButtonPressed += OnKeyBoardDoneButtonPressed;
+
+ WireUpForceUpdateSizeRequested(item, tvc, tv);
+
+ UpdateBackground(tvc, entryCell);
+ UpdateLabel(tvc, entryCell);
+ UpdateText(tvc, entryCell);
+ UpdateKeyboard(tvc, entryCell);
+ UpdatePlaceholder(tvc, entryCell);
+ UpdateLabelColor(tvc, entryCell);
+ UpdateHorizontalTextAlignment(tvc, entryCell);
+ UpdateIsEnabled(tvc, entryCell);
+
+ return tvc;
+ }
+
+ static void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ var entryCell = (EntryCell)sender;
+ var realCell = (EntryCellTableViewCell)GetRealCell(entryCell);
+
+ if (e.PropertyName == EntryCell.LabelProperty.PropertyName)
+ UpdateLabel(realCell, entryCell);
+ else if (e.PropertyName == EntryCell.TextProperty.PropertyName)
+ UpdateText(realCell, entryCell);
+ else if (e.PropertyName == EntryCell.PlaceholderProperty.PropertyName)
+ UpdatePlaceholder(realCell, entryCell);
+ else if (e.PropertyName == EntryCell.KeyboardProperty.PropertyName)
+ UpdateKeyboard(realCell, entryCell);
+ else if (e.PropertyName == EntryCell.LabelColorProperty.PropertyName)
+ UpdateLabelColor(realCell, entryCell);
+ else if (e.PropertyName == EntryCell.HorizontalTextAlignmentProperty.PropertyName)
+ UpdateHorizontalTextAlignment(realCell, entryCell);
+ else if (e.PropertyName == Cell.IsEnabledProperty.PropertyName)
+ UpdateIsEnabled(realCell, entryCell);
+ }
+
+ static void OnKeyBoardDoneButtonPressed(object sender, EventArgs e)
+ {
+ var cell = (EntryCellTableViewCell)sender;
+ var model = (EntryCell)cell.Cell;
+
+ model.SendCompleted();
+ }
+
+ static void OnTextFieldTextChanged(object sender, EventArgs eventArgs)
+ {
+ var cell = (EntryCellTableViewCell)sender;
+ var model = (EntryCell)cell.Cell;
+
+ model.Text = cell.TextField.Text;
+ }
+
+ static void UpdateHorizontalTextAlignment(EntryCellTableViewCell cell, EntryCell entryCell)
+ {
+ cell.TextField.TextAlignment = entryCell.HorizontalTextAlignment.ToNativeTextAlignment();
+ }
+
+ static void UpdateIsEnabled(EntryCellTableViewCell cell, EntryCell entryCell)
+ {
+ cell.UserInteractionEnabled = entryCell.IsEnabled;
+ cell.TextLabel.Enabled = entryCell.IsEnabled;
+ cell.DetailTextLabel.Enabled = entryCell.IsEnabled;
+ cell.TextField.Enabled = entryCell.IsEnabled;
+ }
+
+ static void UpdateKeyboard(EntryCellTableViewCell cell, EntryCell entryCell)
+ {
+ cell.TextField.ApplyKeyboard(entryCell.Keyboard);
+ }
+
+ static void UpdateLabel(EntryCellTableViewCell cell, EntryCell entryCell)
+ {
+ cell.TextLabel.Text = entryCell.Label;
+ }
+
+ static void UpdateLabelColor(EntryCellTableViewCell cell, EntryCell entryCell)
+ {
+ cell.TextLabel.TextColor = entryCell.LabelColor.ToUIColor(DefaultTextColor);
+ }
+
+ static void UpdatePlaceholder(EntryCellTableViewCell cell, EntryCell entryCell)
+ {
+ cell.TextField.Placeholder = entryCell.Placeholder;
+ }
+
+ static void UpdateText(EntryCellTableViewCell cell, EntryCell entryCell)
+ {
+ if (cell.TextField.Text == entryCell.Text)
+ return;
+ // double sets side effect on iOS, YAY
+ cell.TextField.Text = entryCell.Text;
+ }
+
+ class EntryCellTableViewCell : CellTableViewCell
+ {
+ public EntryCellTableViewCell(string cellName) : base(UITableViewCellStyle.Value1, cellName)
+ {
+ TextField = new UITextField(new RectangleF(0, 0, 100, 30)) { BorderStyle = UITextBorderStyle.None };
+
+ TextField.EditingChanged += TextFieldOnEditingChanged;
+ TextField.ShouldReturn = OnShouldReturn;
+
+ ContentView.AddSubview(TextField);
+ }
+
+ public UITextField TextField { get; }
+
+ public event EventHandler KeyboardDoneButtonPressed;
+
+ public override void LayoutSubviews()
+ {
+ base.LayoutSubviews();
+
+ // simple algorithm to generally line up entries
+ var start = (nfloat)Math.Round(Math.Max(Frame.Width * 0.3, TextLabel.Frame.Right + 10));
+ TextField.Frame = new RectangleF(start, (Frame.Height - 30) / 2, Frame.Width - TextLabel.Frame.Left - start, 30);
+ // Centers TextField Content (iOS6)
+ TextField.VerticalAlignment = UIControlContentVerticalAlignment.Center;
+ }
+
+ public event EventHandler TextFieldTextChanged;
+
+ bool OnShouldReturn(UITextField view)
+ {
+ var handler = KeyboardDoneButtonPressed;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+
+ TextField.ResignFirstResponder();
+ return true;
+ }
+
+ void TextFieldOnEditingChanged(object sender, EventArgs eventArgs)
+ {
+ var handler = TextFieldTextChanged;
+ if (handler != null)
+ handler(this, EventArgs.Empty);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Cells/ImageCellRenderer.cs b/Xamarin.Forms.Platform.iOS/Cells/ImageCellRenderer.cs
new file mode 100644
index 00000000..ade59e82
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Cells/ImageCellRenderer.cs
@@ -0,0 +1,70 @@
+using System.ComponentModel;
+using System.Threading.Tasks;
+#if __UNIFIED__
+using UIKit;
+using Foundation;
+
+#else
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class ImageCellRenderer : TextCellRenderer
+ {
+ public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
+ {
+ var result = (CellTableViewCell)base.GetCell(item, reusableCell, tv);
+
+ var imageCell = (ImageCell)item;
+
+ WireUpForceUpdateSizeRequested(item, result, tv);
+
+ SetImage(imageCell, result);
+
+ return result;
+ }
+
+ protected override void HandlePropertyChanged(object sender, PropertyChangedEventArgs args)
+ {
+ var tvc = (CellTableViewCell)sender;
+ var imageCell = (ImageCell)tvc.Cell;
+
+ base.HandlePropertyChanged(sender, args);
+
+ if (args.PropertyName == ImageCell.ImageSourceProperty.PropertyName)
+ SetImage(imageCell, tvc);
+ }
+
+ async void SetImage(ImageCell cell, CellTableViewCell target)
+ {
+ var source = cell.ImageSource;
+
+ target.ImageView.Image = null;
+
+ IImageSourceHandler handler;
+
+ if (source != null && (handler = Registrar.Registered.GetHandler<IImageSourceHandler>(source.GetType())) != null)
+ {
+ UIImage uiimage;
+ try
+ {
+ uiimage = await handler.LoadImageAsync(source).ConfigureAwait(false);
+ }
+ catch (TaskCanceledException)
+ {
+ uiimage = null;
+ }
+
+ NSRunLoop.Main.BeginInvokeOnMainThread(() =>
+ {
+ target.ImageView.Image = uiimage;
+ target.SetNeedsLayout();
+ });
+ }
+ else
+ target.ImageView.Image = null;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Cells/SwitchCellRenderer.cs b/Xamarin.Forms.Platform.iOS/Cells/SwitchCellRenderer.cs
new file mode 100644
index 00000000..ed7ddc10
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Cells/SwitchCellRenderer.cs
@@ -0,0 +1,94 @@
+using System;
+using System.ComponentModel;
+using System.Drawing;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class SwitchCellRenderer : CellRenderer
+ {
+ const string CellName = "Xamarin.SwitchCell";
+
+ public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
+ {
+ var tvc = reusableCell as CellTableViewCell;
+ UISwitch uiSwitch = null;
+ if (tvc == null)
+ tvc = new CellTableViewCell(UITableViewCellStyle.Value1, CellName);
+ else
+ {
+ uiSwitch = tvc.AccessoryView as UISwitch;
+ tvc.Cell.PropertyChanged -= OnCellPropertyChanged;
+ }
+
+ SetRealCell(item, tvc);
+
+ if (uiSwitch == null)
+ {
+ uiSwitch = new UISwitch(new RectangleF());
+ uiSwitch.ValueChanged += OnSwitchValueChanged;
+ tvc.AccessoryView = uiSwitch;
+ }
+
+ var boolCell = (SwitchCell)item;
+
+ tvc.Cell = item;
+ tvc.Cell.PropertyChanged += OnCellPropertyChanged;
+ tvc.AccessoryView = uiSwitch;
+ tvc.TextLabel.Text = boolCell.Text;
+
+ uiSwitch.On = boolCell.On;
+
+ WireUpForceUpdateSizeRequested(item, tvc, tv);
+
+ UpdateBackground(tvc, item);
+ UpdateIsEnabled(tvc, boolCell);
+
+ return tvc;
+ }
+
+ void OnCellPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ var boolCell = (SwitchCell)sender;
+ var realCell = (CellTableViewCell)GetRealCell(boolCell);
+
+ if (e.PropertyName == SwitchCell.OnProperty.PropertyName)
+ ((UISwitch)realCell.AccessoryView).SetState(boolCell.On, true);
+ else if (e.PropertyName == SwitchCell.TextProperty.PropertyName)
+ realCell.TextLabel.Text = boolCell.Text;
+ else if (e.PropertyName == Cell.IsEnabledProperty.PropertyName)
+ UpdateIsEnabled(realCell, boolCell);
+ }
+
+ void OnSwitchValueChanged(object sender, EventArgs eventArgs)
+ {
+ var view = (UIView)sender;
+ var sw = (UISwitch)view;
+
+ CellTableViewCell realCell = null;
+ while (view.Superview != null && realCell == null)
+ {
+ view = view.Superview;
+ realCell = view as CellTableViewCell;
+ }
+
+ if (realCell != null)
+ ((SwitchCell)realCell.Cell).On = sw.On;
+ }
+
+ void UpdateIsEnabled(CellTableViewCell cell, SwitchCell switchCell)
+ {
+ cell.UserInteractionEnabled = switchCell.IsEnabled;
+ cell.TextLabel.Enabled = switchCell.IsEnabled;
+ cell.DetailTextLabel.Enabled = switchCell.IsEnabled;
+ var uiSwitch = cell.AccessoryView as UISwitch;
+ if (uiSwitch != null)
+ uiSwitch.Enabled = switchCell.IsEnabled;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Cells/TextCellRenderer.cs b/Xamarin.Forms.Platform.iOS/Cells/TextCellRenderer.cs
new file mode 100644
index 00000000..41c43341
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Cells/TextCellRenderer.cs
@@ -0,0 +1,73 @@
+using System.ComponentModel;
+#if __UNIFIED__
+using UIKit;
+
+#else
+using MonoTouch.UIKit;
+#endif
+
+namespace Xamarin.Forms.Platform.iOS
+{
+ public class TextCellRenderer : CellRenderer
+ {
+ static readonly Color DefaultDetailColor = new Color(.32, .4, .57);
+ static readonly Color DefaultTextColor = Color.Black;
+
+ public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
+ {
+ var textCell = (TextCell)item;
+
+ var tvc = reusableCell as CellTableViewCell;
+ if (tvc == null)
+ tvc = new CellTableViewCell(UITableViewCellStyle.Subtitle, item.GetType().FullName);
+ else
+ tvc.Cell.PropertyChanged -= tvc.HandlePropertyChanged;
+
+ tvc.Cell = textCell;
+ textCell.PropertyChanged += tvc.HandlePropertyChanged;
+ tvc.PropertyChanged = HandlePropertyChanged;
+
+ tvc.TextLabel.Text = textCell.Text;
+ tvc.DetailTextLabel.Text = textCell.Detail;
+ tvc.TextLabel.TextColor = textCell.TextColor.ToUIColor(DefaultTextColor);
+ tvc.DetailTextLabel.TextColor = textCell.DetailColor.ToUIColor(DefaultDetailColor);
+
+ WireUpForceUpdateSizeRequested(item, tvc, tv);
+
+ UpdateIsEnabled(tvc, textCell);
+
+ UpdateBackground(tvc, item);
+
+ return tvc;
+ }
+
+ protected virtual void HandlePropertyChanged(object sender, PropertyChangedEventArgs args)
+ {
+ var tvc = (CellTableViewCell)sender;
+ var textCell = (TextCell)tvc.Cell;
+ if (args.PropertyName == TextCell.TextProperty.PropertyName)
+ {
+ tvc.TextLabel.Text = ((TextCell)tvc.Cell).Text;
+ tvc.TextLabel.SizeToFit();
+ }
+ else if (args.PropertyName == TextCell.DetailProperty.PropertyName)
+ {
+ tvc.DetailTextLabel.Text = ((TextCell)tvc.Cell).Detail;
+ tvc.DetailTextLabel.SizeToFit();
+ }
+ else if (args.PropertyName == TextCell.TextColorProperty.PropertyName)
+ tvc.TextLabel.TextColor = textCell.TextColor.ToUIColor(DefaultTextColor);
+ else if (args.PropertyName == TextCell.DetailColorProperty.PropertyName)
+ tvc.DetailTextLabel.TextColor = textCell.DetailColor.ToUIColor(DefaultTextColor);
+ else if (args.PropertyName == Cell.IsEnabledProperty.PropertyName)
+ UpdateIsEnabled(tvc, textCell);
+ }
+
+ static void UpdateIsEnabled(CellTableViewCell cell, TextCell entryCell)
+ {
+ cell.UserInteractionEnabled = entryCell.IsEnabled;
+ cell.TextLabel.Enabled = entryCell.IsEnabled;
+ cell.DetailTextLabel.Enabled = entryCell.IsEnabled;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Platform.iOS/Cells/ViewCellRenderer.cs b/Xamarin.Forms.Platform.iOS/Cells/ViewCellRenderer.cs
new file mode 100644
index 00000000..b1416295
--- /dev/null
+++ b/Xamarin.Forms.Platform.iOS/Cells/ViewCellRenderer.cs
@@ -0,0 +1,176 @@
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+#if __UNIFIED__
+using UIKit;
+#else
+using MonoTouch.UIKit;
+using System.Drawing;
+#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 ViewCellRenderer : CellRenderer
+ {
+ public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
+ {
+ var viewCell = (ViewCell)item;
+
+ var cell = reusableCell as ViewTableCell;
+ if (cell == null)
+ cell = new ViewTableCell(item.GetType().FullName);
+ else
+ cell.ViewCell.PropertyChanged -= ViewCellPropertyChanged;
+
+ viewCell.PropertyChanged += ViewCellPropertyChanged;
+ cell.ViewCell = viewCell;
+
+ WireUpForceUpdateSizeRequested(item, cell, tv);
+
+ UpdateBackground(cell, item);
+ UpdateIsEnabled(cell, viewCell);
+ return cell;
+ }
+
+ static void UpdateIsEnabled(ViewTableCell cell, ViewCell viewCell)
+ {
+ cell.UserInteractionEnabled = viewCell.IsEnabled;
+ cell.TextLabel.Enabled = viewCell.IsEnabled;
+ }
+
+ void ViewCellPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ var viewCell = (ViewCell)sender;
+ var realCell = (ViewTableCell)GetRealCell(viewCell);
+
+ if (e.PropertyName == Cell.IsEnabledProperty.PropertyName)
+ UpdateIsEnabled(realCell, viewCell);
+ }
+
+ internal class ViewTableCell : UITableViewCell, INativeElementView
+ {
+ WeakReference<IVisualElementRenderer> _rendererRef;
+
+ ViewCell _viewCell;
+
+ public ViewTableCell(string key) : base(UITableViewCellStyle.Default, key)
+ {
+ }
+
+ public ViewCell ViewCell
+ {
+ get { return _viewCell; }
+ set
+ {
+ if (_viewCell == value)
+ return;
+ UpdateCell(value);
+ }
+ }
+
+ Element INativeElementView.Element
+ {
+ get { return ViewCell; }
+ }
+
+ public override void LayoutSubviews()
+ {
+ //This sets the content views frame.
+ base.LayoutSubviews();
+
+ var contentFrame = ContentView.Frame;
+
+ Layout.LayoutChildIntoBoundingRegion(ViewCell.View, contentFrame.ToRectangle());
+
+ if (_rendererRef == null)
+ return;
+
+ IVisualElementRenderer renderer;
+ if (_rendererRef.TryGetTarget(out renderer))
+ renderer.NativeView.Frame = contentFrame;
+ }
+
+ public override SizeF SizeThatFits(SizeF size)
+ {
+ IVisualElementRenderer renderer;
+ if (!_rendererRef.TryGetTarget(out renderer))
+ return base.SizeThatFits(size);
+
+ double width = size.Width;
+ var height = size.Height > 0 ? size.Height : double.PositiveInfinity;
+ var result = renderer.Element.Measure(width, height);
+
+ // make sure to add in the separator
+ return new SizeF(size.Width, (float)result.Request.Height + 1f / UIScreen.MainScreen.Scale);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ IVisualElementRenderer renderer;
+ if (_rendererRef != null && _rendererRef.TryGetTarget(out renderer) && renderer.Element != null)
+ {
+ var platform = renderer.Element.Platform as Platform;
+ if (platform != null)
+ platform.DisposeModelAndChildrenRenderers(renderer.Element);
+
+ _rendererRef = null;
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ IVisualElementRenderer GetNewRenderer()
+ {
+ var newRenderer = Platform.CreateRenderer(_viewCell.View);
+ _rendererRef = new WeakReference<IVisualElementRenderer>(newRenderer);
+ ContentView.AddSubview(newRenderer.NativeView);
+ return newRenderer;
+ }
+
+ void UpdateCell(ViewCell cell)
+ {
+ if (_viewCell != null)
+ Device.BeginInvokeOnMainThread(_viewCell.SendDisappearing);
+
+ _viewCell = cell;
+ Device.BeginInvokeOnMainThread(_viewCell.SendAppearing);
+
+ IVisualElementRenderer renderer;
+ if (_rendererRef == null || !_rendererRef.TryGetTarget(out renderer))
+ renderer = GetNewRenderer();
+ else
+ {
+ if (renderer.Element != null && renderer == Platform.GetRenderer(renderer.Element))
+ renderer.Element.ClearValue(Platform.RendererProperty);
+
+ var type = Registrar.Registered.GetHandlerType(_viewCell.View.GetType());
+ if (renderer.GetType() == type || (renderer is Platform.DefaultRenderer && type == null))
+ renderer.SetElement(_viewCell.View);
+ else
+ {
+ //when cells are getting reused the element could be already set to another cell
+ //so we should dispose based on the renderer and not the renderer.Element
+ var platform = renderer.Element.Platform as Platform;
+ platform.DisposeRendererAndChildren(renderer);
+ renderer = GetNewRenderer();
+ }
+ }
+
+ Platform.SetRenderer(_viewCell.View, renderer);
+ }
+ }
+ }
+} \ No newline at end of file