{"id":6391,"date":"2018-09-27T20:52:47","date_gmt":"2018-09-27T20:52:47","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=6391"},"modified":"2018-09-27T20:52:47","modified_gmt":"2018-09-27T20:52:47","slug":"handling-orientation-in-xamarin-forms","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/handling-orientation-in-xamarin-forms\/","title":{"rendered":"Handling orientation in Xamarin Forms"},"content":{"rendered":"<p>Many years ago I wrote some Windows CE\/Pocket PC code. One of the problems was handling different orientation in the same UI, so for example when the device is switched from Portrait to Landscape &#8211; in some cases we can use the same layout in both orientations other times and probably in more cases, this isn&#8217;t so simple.<\/p>\n<p>Xamarin Forms does not raise orientation events or the likes, instead we will need to override a Pages OnSizeAllocated method, for example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nprotected override void OnSizeAllocated(double width, double height)\r\n{\r\n   base.OnSizeAllocated(width, height);\r\n\r\n   if (width &lt; height)\r\n   {\r\n       \/\/ portrait orientation\r\n   }\r\n   else if (height &lt; width)\r\n   {\r\n       \/\/ landscape orientation\r\n   }\r\n   else\r\n   {\r\n      \/\/ square layout\r\n   }\r\n}\r\n<\/pre>\n<p><em>Note: There is also a Device Orientation plugin\/nuget package for Xamarin Forms which raises events when orientation changes.<\/em><\/p>\n<p>Now we can handle changes to our layout in one of few ways. <\/p>\n<p>We might be to reparent controls, changing layout orientation and\/or changes to rows\/columns and so on, all in code. This is fairly efficient in terms of reusing the existing controls but is obviously less useful from a design perspective.<\/p>\n<p>We might be able to create the layout in such a way that we can just change orientation of StackLayout&#8217;s etc. Hence changing a few properties to reflect the new orientation. This might be more difficult to setup successfully on complex pages.<\/p>\n<p>An alternative method, which is a little wasteful in turns of control creation, but gives us a good design story, is two design two ContentView&#8217;s, one for Portrait and one for Landscape. Obviously we&#8217;ll need to bind the controls to the same view model properties etc. However, with this solution we can more rapidly get our UI up and running.<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;controls:OrientationView&gt;\r\n   &lt;controls:OrientationView.Landscape&gt;\r\n      &lt;views:LandscapeView \/&gt;\r\n   &lt;\/controls:OrientationView.Landscape&gt;\r\n   &lt;controls:OrientationView.Portrait&gt;\r\n      &lt;views:PortraitView \/&gt;\r\n   &lt;\/controls:OrientationView.Portrait&gt;\r\n&lt;\/controls:OrientationView&gt;\r\n<\/pre>\n<p>The OrientationView, might look like this<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic class OrientationView : ContentView\r\n{\r\n   public View Landscape { get; set; }\r\n   public View Portrait { get; set; }\r\n   public View Square { get; set; }\r\n\r\n   private Page _parentPage;\r\n\r\n   protected override void OnParentSet()\r\n   {\r\n      base.OnParentSet();\r\n\r\n      _parentPage = this.GetParentPage();\r\n      if (_parentPage != null)\r\n      {\r\n         _parentPage.SizeChanged += PageOnSizeChanged;\r\n      }\r\n   }\r\n\r\n   private void PageOnSizeChanged(object sender, EventArgs eventArgs)\r\n   {\r\n      if (_parentPage.Width &lt; _parentPage.Height)\r\n      {\r\n         Content = Portrait ?? Landscape ?? Square;\r\n      }\r\n      else if (_parentPage.Height &lt; _parentPage.Width)\r\n      {\r\n         Content = Landscape ?? Portrait ?? Square;\r\n      }\r\n      else\r\n      {\r\n         Content = Square ?? Portrait ?? Landscape;\r\n      }\r\n   }\r\n}\r\n<\/pre>\n<p>Here&#8217;s the GetParentPage extension method<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic static class ViewExtensions\r\n{\r\n   public static Page GetParentPage(this VisualElement element)\r\n   {\r\n      if (element != null)\r\n      {\r\n         var parent = element.Parent;\r\n         while (parent != null)\r\n         {\r\n            if (parent is Page parentPage)\r\n            {\r\n               return parentPage;\r\n            }\r\n            parent = parent.Parent;\r\n         }\r\n      }\r\n      return null;\r\n   }\r\n}\r\n<\/pre>\n<p>This allows us to basically design totally different UI&#8217;s for portrait and landscape, maybe adding extra controls in landscape and removing in portrait. The obvious downside is the duplication of controls.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Many years ago I wrote some Windows CE\/Pocket PC code. One of the problems was handling different orientation in the same UI, so for example when the device is switched from Portrait to Landscape &#8211; in some cases we can use the same layout in both orientations other times and probably in more cases, this [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[122],"tags":[],"class_list":["post-6391","post","type-post","status-publish","format-standard","hentry","category-xamarin-forms"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/6391","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=6391"}],"version-history":[{"count":4,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/6391\/revisions"}],"predecessor-version":[{"id":6517,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/6391\/revisions\/6517"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=6391"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=6391"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=6391"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}