We've already seen how Xamarin Forms makes it easy to create cross-platform applications that share common layout and behavior. While the included controls like ListView encapsulate a lot of useful behavior, they don't make for the fanciest layouts. In early versions of Falafel 2 Go we had a simple ListView control as the main page, displaying all of the Activities we want to showcase, such as Blogs and Training as well as links to our social profiles. This worked great for testing but didn't make for a very compelling application interface: In an attempt to at least add some visual elements, we replaced the default ListView DataTemplate with an ImageCell, which used a new Icon property to add an image to the list. It helped, but wasn't really much of an improvement. We also briefly experimented with implementing a Master-Detail page to recreate the "sidebar" or "drawer" interface of our previous version of Falafel 2 Go: However, in addition to still not being a very inviting interface, we thought that the rewrite was a great opportunity to rebrand the application with a spiffy new design. Finally, our talented designer Matt stepped in with yet another fantastic design concept, which of course you can see today in the live application. However, it wasn't immediately clear how to go about actually implementing this design. The variable grid layout certainly didn't lend itself to the ListView so we needed a new approach. Previous experience with Windows Phone XAML applications shows that similar layouts can been realized by using the Grid. This XAML control can stretch to fill the screen while also allowing the content within each cell to stretch to fill as well, and even set relative sizes of the different rows and columns. Fortunately, Xamarin Forms also includes a Grid control, so it made sense to use this to create a Grid layout with variable row heights to accommodate the different sizes of the buttons. This would allow the controls to render in the desired layout while still allowing the grid to easily scale to larger devices like the iPad and Android Tablets.
Nested Grids
The biggest challenge was accommodating the varied sizes between the two main buttons for Blog and Training and the remaining two rows of buttons underneath. Because Xamarin Forms (currently) lacks a visual designer, it was difficult to pinpoint the best markup to layout the grid exactly as we wanted. In the end, it made sense to use two grids so that the top could have the two columns required for the main buttons, with a second three-column grid below. It may also be possible to create a similar layout with a single grid using Column and Row spanning to achieve the positioning, but we found this approach to be sufficient and simple enough for our needs. We originally placed both of these grids in a StackLayout control but this prevented the Grids from correctly stretching to exactly fill the screen. In addition, we needed the top Grid to be a specific ratio of height larger than the second in order to achieve the larger layout for the main buttons. In the end, given these precise layout requirements, it made sense to wrap both Grid controls in yet another Grid, this one with two rows set at a ratio so that each Grid could fill the appropriate area while still stretching to fill the screen. At last here is the final markup for the Grids for the desired layout. From top to bottom, the first grid is the main container with two rows to contain each remaining grid, with the next being the top row of two columns and the final Grid at the bottom the remaining 3 column rows.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="3*" />
<RowDefinition Height="4*" />
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!--
Top row of main buttons go here -->
</Grid>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!--
Bottom two rows of buttons go here -->
</Grid>
</Grid>
It was also interesting to learn that for the Xamarin Grid, we needed to explicitly define either the Width property for Columns or the Height property for Rows, even if it was the only one in the Grid. An important distinction, as I do not believe Windows XAML has this requirement.
Next Steps
Now we needed to add the various buttons for launching the navigation to the different parts of the app. This too proved to be an interesting challenge as we wanted to have both the image and text be tap targets, while not making the entire cell a button (which would make the blank areas targets). We also wanted to avoid having to duplicate the code required to define each button, especially if we decide to add new ones later, or modify all of the button styles at once in a future release. We needed something more modular, like a reusable User Control. We'll take a closer look at how we overcame this challenge in our next post. Until then be sure to check out Falafel 2 Go and share your feedback and questions below, and as always, I hope this was helpful!
Enjoyed this post and/or found it useful?