Without XAML
Without XAML

While XAML is the preferred method for designing a Xamarin Forms UI, whatever can be achieved in XAML can be done using C# in the code-behind file. Building a Xamarin Forms UI - Code Behind looks at manipulating controls in Xamarin Forms UI using C# code. We take a content view from the earlier Layout Containers course and see how to adapt to changing device orientation in the code-behind file.

Source code


Whatever you can do in Xaml, you can do with code. I'll address the landscape orientation issue with the grid layout using C# to show how the UI can be manipulated from the code behind file. Probably the biggest disadvantage of building the UI with code instead of Xaml is that the hot reload functionality enabling you to visualize the screen is not available. The first thing we need to do in GridLayoutView.xaml.cs is detect when the screen orientation changes. We can do this by overriding the protected onSizeAllocated method of the ContentView class. There is no method to determine the device orientation per se, but we infer the orientation by comparing the width and height of the screen. We are in portrait mode if the height is greater than the width; otherwise, it's landscape. Before calling our custom code, we need to execute the base functionality of the onSizeAllocated method. This event will also be triggered when the view is first shown but before rendered, so I don't want to execute any code until we know what orientation we're in; hence, only when the width is greater than zero. I'll put the custom code in a private method called ReconfigureLayout that takes a boolean parameter specifying the orientation. We'll have two code branches - one for portrait and one for landscape. I'll declare a private Boolean member to store the screen orientation, which will be updated when OnSizeAllocated is triggered via ReconfigureLayout.

I'm not going to just resize the UI elements for landscape; I'm going to change its layout by adding an extra column in landscape mode. This means I'll need to know how many columns the grid has, and obviously, I will need to reference the grid. In the xaml view, I'll give the grid a name. Once named, the grid object is available in Visual Studio's IntelliSense. This code says if the screen is in portrait orientation, but the layout grid has four columns defined, meaning it is in landscape mode, we need to change the grid to portrait mode. Below that, we have the else condition, which is the reverse. The screen is in landscape orientation, but the grid is in portrait mode.

Remember, in the xaml, the bottom three rows of the grid are not used, so the first thing I'll do is remove them. Next, I'll add the fourth column. Xamarin has row and column definition classes that enable us to define their heights and width using the proportional star notation instead of being limited to a pixel count in the code behind file. In accordance with best practice I'll comment the code, but unfortunately Visual Studio is yet to incorporate a spell checker.

I want to move the three boxes from the bottom row to the new column. Once again, I'll have to go into the xaml and give those frames names to reference them in the code. Having removed those frames from the grid, I can now add them back into the new fourth column. Remember, the grid row and column idexes start at zero, so the fourth column is referenced with an index of 3.

Finally, I'll create new margins to reflect the frames' new positions.

The portrait orientation code is the reverse, funnily enough. So, we remove the named frames and then the fourth column and add the frames back into the fourth row before adding the three empty rows and readjusting the margins. Let's run that and see how it works. While I'm at it, I will apply the main page button style to the controls button. Well, the idea is good, but we need to fine-tune the layout. Let's remove the fourth row, which is also surplus to requirements in landscape orientation. In the portrait code, 

I'll need to add it back in before I reposition the bottom red, yellow, and blue frames, remembering the fourth row is set at 0.6 of a star height. 


Almost there, but I still need to adjust the right-hand margin for the top left box and add some padding to the bottom of the grid. I incorrectly adjusted the margin in the portrait code rather than the landscape code, so I'll just quickly fix that. Now I'll add some padding around the bottom of the grid. Margin is the space around the grid, while padding is internal to the grid, the margin around the grid's content. Two things to note here; firstly, the commented out scroll view element, so instead of having the elements fit perfectly in the screen, we could have just put the whole grid within a scroll view. Secondly, if I adjust the row height of the fourth row while in landscape orientation, we get a squiggly line because that row doesn't currently exist. I need to stop the debugging session to make the required adjustments. Because the padding has made the grid area smaller, I'll make the two bottom rows proportionally bigger, and I'll need to replicate that change when adding the fourth row back in portrait mode. Okay, third time is the charm. Let's run that again. That looks great. Well, it looks how I intended it to. Let's now see how it looks on an iPhone. From the iOS menu under tools, I'll pair to my Mac running the iOS simulator and set the start-up project to Xaml_UI.iOS. The simulator will take a little while to start up, and once it has, we can see that our custom font is correctly rendered on the buttons. Although the button corner radii do seem more rounded than the android version. Looking at the grid layout, while similar, it does seem more bunched up, and the drop shadow effect is far more pronounced. Anyway, let's see how the rotation performs. Haha, that's funny. Well, it works, but that's not what I was expecting. Let's go to the simulator on the Mac to get a better view. Right, and this is why you want to test your app on multiple devices. While it has been rendered correctly, for this iPhone model, I should add padding to the right-hand side of the grid when in landscape mode to avoid the camera cut out. To be fair, this might be an artifact of the simulator, and if I was running this on an actual iPhone, this might not be an issue. Later we'll see how to address platform-specific formatting.

About the Author
Learning Paths

Hallam is a software architect with over 20 years experience across a wide range of industries. He began his software career as a  Delphi/Interbase disciple but changed his allegiance to Microsoft with its deep and broad ecosystem. While Hallam has designed and crafted custom software utilizing web, mobile and desktop technologies, good quality reliable data is the key to a successful solution. The challenge of quickly turning data into useful information for digestion by humans and machines has led Hallam to specialize in database design and process automation. Showing customers how leverage new technology to change and improve their business processes is one of the key drivers keeping Hallam coming back to the keyboard. 

Covered Topics