Layouts
Layouts are container elements used to allocate user controls across a design surface. In order to satisfy platform imperatives, layouts can be used to align, stack, and position view elements. The different types of layouts are as follows:
- StackLayout: This is one of the most overused layout structures in Xamarin.Forms. It is used to stack various view and other layout elements with prescribed requirements. These requirements are defined through various dependency or instance properties, such as alignment options and dimension requests.
For instance, on the ItemView page, we use the StackLayout to combine the Image of the given item with the title and description:
<StackLayout Padding="10" Orientation="Vertical">
<Image Source="{Binding Image}" HorizontalOptions="FillAndExpand"/>
<Label Text="{Binding Title}" FontSize="Large" />
<Label Text="{Binding Description}" />
</StackLayout>
In this setup, the important declarations are the Orientation, which defines that the stacking should occur vertically. HorizontalOptions is defined for the Image element, which allows the Image to expand both horizontally and vertically, depending on the available space. StackLayout can be employed to create orientation-change-responsive behavior.
- FlexLayout: This can be used to create fluid and flexible arrangements of view elements that can adapt to the available surface. FlexLayout has many available directives that developers can use to define alignment directions. In order to demonstrate just a few of these, let's assumeItemView requires an implementation of a horizontal layout, where certain features are listed in a floating stack that can wrap into as many rows as required:
<StackLayout Padding="10" Orientation="Vertical" Spacing="10">
<Label Text="{Binding Title}" FontSize="Large" />
<Image Source="{Binding Image}" HorizontalOptions="FillAndExpand" />
<FlexLayout Direction="Row" Wrap="Wrap">
<Label Text="Feature 1" Margin="4" VerticalTextAlignment="Center" BackgroundColor="Gray" />
<Label Text="Feat. 2" Margin="4" VerticalTextAlignment="Center" BackgroundColor="Lime"/>
<!-- Additional Labels -->
</FlexLayout>
<Label Text="{Binding Description}" />
</StackLayout>
This would create a design structure similar to the one described in the fluid layout responsive UI pattern:
- Grid: If it is not desired for the views in a layout to expand and trigger layout cycles—in other words, if a certain page requires a more top-down layout structure (that is, with the parent element determining the layout)—then Grid would be the most suitable control. Using the Grid layout, controls can be laid out in accordance with column and row definitions, which can be adjusted to respond to control size changes or the overall size of the Grid.
While creating the control template for our page, we used a Grid to create a rigid structure to place the footer with an absolute height value, while allowing the rest of the screen to be covered by the content presenter:
<ControlTemplate x:Key="PageTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="25" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Row="0" />
<BoxView Grid.Row="1" Color="Navy" />
<Label Grid.Row="1" Margin="10,0,0,0" Text="(c) Hands-On
Cross Platform 2018" TextColor="White"
VerticalOptions="Center" />
</Grid>
</ControlTemplate>
Note that we used a margin value for the label. To avoid using the margin, we could have created a column definition with a fixed value and, according to the desired outcome, set that margin column to apply to the content presenter as well:
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="25" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10 />
<ColumnDefinition />
<ColumnDefinition Width="10" />
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="1" Grid.Row="0" />
<BoxView Grid.Row="1" Grid.ColumnSpan="3" Color="Navy" />
<Label Grid.Row="1" Grid.Column="1" Text="(c) Hands-On Cross
Platform 2018" TextColor="White" VerticalOptions="Center" />
</Grid>
With this setup, the BoxView will expand on three columns, while the footer text and the actual content will be isolated to the second column, Column-1, with Column-0 and Column-2 acting as the margins.
Grid can also be used only to structure a certain segment of a view. For instance, if we were to add a specifications section in our ItemView page, it would look similar to the following:
<StackLayout Padding="10" Orientation="Vertical" Spacing="10">
<!-- Removed for Brevity -->
<Label Text="{Binding Description}" />
<Label Text="Specifications" Font="Bold" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="5*" />
</Grid.ColumnDefinitions>
<Label Text="Specification 1"
Grid.Column="0" Grid.Row="0"/>
<Label Text="Value for Specification"
Grid.Column="1" Grid.Row="0" TextColor="Gray"/>
<Label Text="Another Spec."
Grid.Column="0" Grid.Row="1" />
<Label Text="Value for Specification that is a little
longer"
Grid.Column="1" Grid.Row="1" TextColor="Gray"/>
<!-- Additional Specs go here -->
</Grid>
</StackLayout>
Notice the columns are set to use 3/8th and 5/8th of the screen to result in the optimal use of the space available. This would create a view similar to the following:
After adding this last element to the screen, you might notice that the screen space is exhausted vertically, so the final grid element might overflow out of the view port, depending on the screen size.
- ScrollView: In order to allow the scrolling of the screen so that the whole content is visible to the user, we can introduce ScrollView. ScrollView is another prominent layout element, which acts as a scrollable container for the contained view elements.
In order to enable the scrolling of the screen so that all the specifications are visible, we can simply wrap the main layout in ItemView.xaml in a ScrollView:
<ContentPage.Content>
<ScrollView>
<StackLayout Padding="10" Orientation="Vertical"
Spacing="10">
<!-- Removed for brevity -->
</StackLayout>
</ScrollView>
</ContentPage.Content>
An additional use of ScrollView comes into the picture when Entry fields are involved. When the user taps on an Entry field, the behavior on a mobile device is that the keyboard slides up from the bottom of the screen, creating a vertical offset and decreasing the design space. In the view that the Entry is contained in, the keyboard might overlap with the Entry that is currently in focus. This would create an undesirable user experience. In order to remedy this behavior, the form content should be placed in ScrollView so that the appearance of the keyboard does not push the Entry in question out of the bounds of the screen.
- AbsoluteLayout and RelativeLayout: These are the other layout options that we have not covered so far. Both of these layouts, generally speaking, treat the view almost like a canvas and allow items to be placed on top of each other, using either the current screen (in the case of AbsoluteLayout) or the other controls (in the case of RelativeLayout) as a reference for positioning.
For instance, if we were to place a floating action button (FAB), from Material Design on our ListItemView, we could easily achieve that using an absolute layout, by placing the button in the bottom-right corner of the screen (that is, position proportional) and adding a margin on our FAB:
<AbsoluteLayout>
<ListView
ItemsSource="{Binding Items}"
ItemTapped="Handle_ItemTapped"
SeparatorVisibility="None" >
<ListView.ItemTemplate>
<DataTemplate>
<!-- Removed for brevity -->
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Image
Source="AddIcon.png"
HeightRequest="60"
WidthRequest="60"
AbsoluteLayout.LayoutFlags="PositionProportional"
AbsoluteLayout.LayoutBounds="1.0,1.0"
Margin="10"/>
</AbsoluteLayout>
This would create a view where the FAB (that is, the image used instead of a FAB) is displayed over the list view items:
Additionally, RelativeLayout, in similar fashion, allows developers to create proportional calculations between elements, as well as for the view itself.