{"id":11470,"date":"2014-06-11T11:00:40","date_gmt":"2014-06-11T15:00:40","guid":{"rendered":"http:\/\/blog.xamarin.com\/?p=11470"},"modified":"2014-06-11T11:00:40","modified_gmt":"2014-06-11T15:00:40","slug":"using-custom-uiviewcontrollers-in-xamarin-forms-on-ios","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/using-custom-uiviewcontrollers-in-xamarin-forms-on-ios\/","title":{"rendered":"Using Custom UIViewControllers in Xamarin.Forms on iOS"},"content":{"rendered":"<p>\t\t\t\tXamarin.Forms abstracts the native controls of Android, iOS, and Windows Phone, allowing developers to create native UIs on each platform from a single, shared C# codebase. This delivers not only reusable user interface code, but also the native user experience that users demand across all platforms.<\/p>\n<p>Sometimes though, we may want to do something that directly uses the platform APIs rather than working at the Xamarin.Forms layer. On iOS we might want to access properties on a <strong>CALayer<\/strong> or work directly with a <strong>UIViewController<\/strong>.<\/p>\n<p><img decoding=\"async\" class=\"aligncenter size-full wp-image-11484\" src=\"\/wp-content\/uploads\/sites\/44\/2019\/04\/iospagerenderer.png\" alt=\"iospagerenderer\" width=\"432\" height=\"421\" \/><\/p>\n<p>Perhaps we already have existing platform specific UI code that we want to reuse in part of our app, but still want to adopt Xamarin.Forms going forwards as needed. Xamarin.Forms shines in this department and is designed to allow us to tap directly into the native platform through a technology known as <em>renderers<\/em>.<\/p>\n<p>We can create a renderer to implement our own native UI code at the control level or even at the page level. Say we want to take a <strong>UIViewController<\/strong> implementation from Xamarin.iOS and bring it into the world of Xamarin.Forms. This can be achieved by implementing a <strong>PageRender<\/strong> in Xamarin.iOS that will be used in our Xamarin.Forms shared UI app logic.<\/p>\n<h2>Image Cropping<\/h2>\n<p>A lot of photo apps today allow their users to crop images. We are able to accomplish this by using gesture recognizers and Core Graphics to allow the user to touch to drag and pinch to resize a cropping rectangle over a photo. Here is a <strong>UIViewController<\/strong> that takes advantage of these platform specific iOS capabilities. (the full code is omitted for brevity):<\/p>\n<pre class=\"lang:csharp decode:true\">\npublic partial class CropperViewController : UIViewController\n{\n  ...\n  public override void ViewDidLoad ()\n  {\n    base.ViewDidLoad ();\n\n    ...\n\n    View.AddSubviews (imageView, cropperView);\n    ...\n<\/pre>\n<p><a href=\"\/wp-content\/uploads\/sites\/44\/2019\/04\/ioscropcrontroller.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-11491\" src=\"\/wp-content\/uploads\/sites\/44\/2019\/04\/ioscropcrontroller.png\" alt=\"ioscropcrontroller\" width=\"249\" height=\"501\" \/><\/a><\/p>\n<p>The Xamarin.iOS implementation involves the following steps which are well-suited to native code:<\/p>\n<ol>\n<li>Draw a transparent overlay on an image<\/li>\n<li>Cut out a rectangle in the overlay<\/li>\n<li>Touch to resize and drag the cropping rectangle<\/li>\n<li>Crop the image to the cropping rectangle<\/li>\n<\/ol>\n<p>To use this controller in a Xamarin.Forms application, rather than deriving directly from <strong>UIViewController<\/strong>, we can derive from <strong>PageRenderer<\/strong>. Since <strong>PageRenderer<\/strong> derives from <strong>UIViewController<\/strong>, all the existing code from the controller&#8217;s implementation will work just fine.<\/p>\n<pre class=\"lang:csharp decode:true\">\npublic class CropperPageRenderer : PageRenderer\n{\n  ...\n  public override void ViewDidLoad ()\n  {\n    base.ViewDidLoad ();\n\n    ...\n\n    View.AddSubviews (imageView, cropperView);\n    ...\n<\/pre>\n<p>Additionally, we may want to apply model data set on the Xamarin.Forms side into the native code. We can achieve this by implementing <strong>OnElementChanged<\/strong>. For example, here we take a string from the <strong>Text<\/strong> field in the Xamarin.Forms <strong>ContentPage<\/strong>, which is of type <strong>CropperPage<\/strong> in this case, and apply it to a native <strong>UILabel<\/strong>.<\/p>\n<pre class=\"lang:csharp decode:true\">\nprotected override void OnElementChanged (VisualElementChangedEventArgs e)\n{\n  base.OnElementChanged (e);\n\n  var page = e.NewElement as CropperPage;\n  var view = NativeView;\n\n  var label = new UILabel (new RectangleF(20, 40, view.Frame.Width-40, 40));\n  label.AdjustsFontSizeToFitWidth = true;\n  label.TextColor = UIColor.White;\n  if (page != null) {\n    label.Text = page.Text;\n  }\n\n  view.Add (label);\n}\n<\/pre>\n<p><img decoding=\"async\" class=\"aligncenter size-full wp-image-11492\" src=\"\/wp-content\/uploads\/sites\/44\/2019\/04\/ioscroprenderer1.png\" alt=\"ioscroprenderer1\" width=\"249\" height=\"501\" \/><\/p>\n<p>The Xamarin.Forms class <strong>CropperPage<\/strong> will use <strong>CropperPageRenderer<\/strong> when we add the following attribute to our custom renderer class:<\/p>\n<pre class=\"lang:csharp decode:true\">\n[assembly:ExportRenderer(typeof(Cropper.CropperPage), typeof(Cropper.iOS.CropperPageRenderer))]\n<\/pre>\n<p>On the Xamarin.Forms side, the <strong>CropperPage<\/strong> is a <strong>ContentPage<\/strong>.<\/p>\n<pre class=\"lang:csharp decode:true\">\npublic class CropperPage : ContentPage\n{\n    public string Text = &quot;Image cropping in native renderer&quot;;\n\n    public CropperPage ()\n    {\n        BackgroundColor = Color.Purple;\n    }\n}\n<\/pre>\n<p>Notice the <strong>Text<\/strong> field that was accessed from <strong>OnModelSet<\/strong> earlier that comes from this class. Also, UI code can be set in the <strong>ContentPage<\/strong> and it is included with the code from the renderer. An example of this is the <strong>BackgroundColor<\/strong>, which is set to purple and is visible in the renderer after the image is cropped:<\/p>\n<p><a href=\"\/wp-content\/uploads\/sites\/44\/2019\/04\/ioscroprenderer2.png.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-11493\" src=\"\/wp-content\/uploads\/sites\/44\/2019\/04\/ioscroprenderer2.png.png\" alt=\"ioscroprenderer2.png\" width=\"249\" height=\"501\" \/><\/a><\/p>\n<p>So as you can see, blending native code with Xamarin.Forms is very straight forward, offering the flexibility to work from a higher level of abstraction, while always having access to the power of the native platform APIs when you want them.<\/p>\n<p>The code from this post is available in my <a href=\"https:\/\/github.com\/mikebluestein\/Cropper\" title=\"Cropper source code\" target=\"_blank\">GitHub repo<\/a>.<\/p>\n<p><a href=\"http:\/\/forums.xamarin.com\/discussion\/18102\/\" target=\"_blank\"><i>Discuss this blog post in the Xamarin Forums<\/i><\/a>\t\t<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Xamarin.Forms abstracts the native controls of Android, iOS, and Windows Phone, allowing developers to create native UIs on each platform from a single, shared C# codebase. This delivers not only reusable user interface code, but also the native user experience that users demand across all platforms. Sometimes though, we may want to do something that [&hellip;]<\/p>\n","protected":false},"author":1932,"featured_media":39167,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[6,4,16],"class_list":["post-11470","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developers","tag-ios","tag-xamarin-platform","tag-xamarin-forms"],"acf":[],"blog_post_summary":"<p>Xamarin.Forms abstracts the native controls of Android, iOS, and Windows Phone, allowing developers to create native UIs on each platform from a single, shared C# codebase. This delivers not only reusable user interface code, but also the native user experience that users demand across all platforms. Sometimes though, we may want to do something that [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/11470","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/users\/1932"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=11470"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/11470\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media\/39167"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=11470"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=11470"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=11470"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}