Choose a Xamarin.Forms Layout
Xamarin.Forms layout classes allow you to arrange and group UI controls in your application. Choosing a layout class requires knowledge of how the layout positions its child elements, and how the layout sizes its child elements. In addition, it may be necessary to nest layouts to create your desired layout.
The following image shows typical layouts that can be achieved with the main Xamarin.Forms layout classes:
StackLayout
A StackLayout
organizes elements in a one-dimensional stack, either horizontally or vertically. The Orientation
property specifies the direction of the elements, and the default orientation is Vertical
. StackLayout
is typically used to arrange a subsection of the UI on a page.
The following XAML shows how to create a vertical StackLayout
containing three Label
objects:
<StackLayout Margin="20,35,20,25">
<Label Text="The StackLayout has its Margin property set, to control the rendering position of the StackLayout." />
<Label Text="The Padding property can be set to specify the distance between the StackLayout and its children." />
<Label Text="The Spacing property can be set to specify the distance between views in the StackLayout." />
</StackLayout>
In a StackLayout
, if an element's size is not explicitly set, it expands to fill the available width, or height if the Orientation
property is set to Horizontal
.
A StackLayout
is often used as a parent layout, which contains other child layouts. However, a StackLayout
should not be used to reproduce a Grid
layout by using a combination of StackLayout
objects. The following code shows an example of this bad practice:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Details.HomePage"
Padding="0,20,0,0">
<StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Name:" />
<Entry Placeholder="Enter your name" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Age:" />
<Entry Placeholder="Enter your age" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Occupation:" />
<Entry Placeholder="Enter your occupation" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Address:" />
<Entry Placeholder="Enter your address" />
</StackLayout>
</StackLayout>
</ContentPage>
This is wasteful because unnecessary layout calculations are performed. Instead, the desired layout can be better achieved by using a Grid
.
Tip
When using a StackLayout
, ensure that only one child element is set to LayoutOptions.Expands
. This property ensures that the specified child will occupy the largest space that the StackLayout
can give to it, and it is wasteful to perform these calculations more than once.
For more information, see Xamarin.Forms StackLayout.
Grid
A Grid
is used for displaying elements in rows and columns, which can have proportional or absolute sizes. A grid's rows and columns are specified with the RowDefinitions
and ColumnDefinitions
properties.
To position elements in specific Grid
cells, use the Grid.Column
and Grid.Row
attached properties. To make elements span across multiple rows and columns, use the Grid.RowSpan
and Grid.ColumnSpan
attached properties.
Note
A Grid
layout should not be confused with tables, and is not intended to present tabular data. Unlike HTML tables, a Grid
is intended for laying out content. For displaying tabular data, consider using a ListView, CollectionView, or TableView.
The following XAML shows how to create a Grid
with two rows and two columns:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Text="Column 0, Row 0"
WidthRequest="200" />
<Label Grid.Column="1"
Text="Column 1, Row 0" />
<Label Grid.Row="1"
Text="Column 0, Row 1" />
<Label Grid.Column="1"
Grid.Row="1"
Text="Column 1, Row 1" />
</Grid>
In this example, sizing works as follows:
- Each row has an explicit height of 50 device-independent units.
- The width of the first column is set to
Auto
, and is therefore as wide as required for its children. In this case, it's 200 device-independent units wide to accommodate the width of the firstLabel
.
Space can be distributed within a column or row by using auto sizing, which lets columns and rows size to fit their content. This is achieved by setting the height of a RowDefinition
, or the width of a ColumnDefinition
, to Auto
. Proportional sizing can also be used to distribute available space among the rows and columns of the grid by weighted proportions. This is achieved by setting the height of a RowDefinition
, or the width of a ColumnDefinition
, to a value that uses the *
operator.
Caution
Try to ensure that as few rows and columns as possible are set to Auto
size. Each auto-sized row or column will cause the layout engine to perform additional layout calculations. Instead, use fixed size rows and columns if possible. Alternatively, set rows and columns to occupy a proportional amount of space with the GridUnitType.Star
enumeration value.
For more information, see Xamarin.Forms Grid.
FlexLayout
A FlexLayout
is similar to a StackLayout
in that it displays child elements either horizontally or vertically in a stack. However, a FlexLayout
can also wrap its children if there are too many to fit in a single row or column, and also enables more granular control of the size, orientation, and alignment of its child elements.
The following XAML shows how to create a FlexLayout
that displays its views in a single column:
<FlexLayout Direction="Column"
AlignItems="Center"
JustifyContent="SpaceEvenly">
<Label Text="FlexLayout in Action" />
<Button Text="Button" />
<Label Text="Another Label" />
</FlexLayout>
In this example, layout works as follows:
- The
Direction
property is set toColumn
, which causes the children of theFlexLayout
to be arranged in a single column of items. - The
AlignItems
property is set toCenter
, which causes each item to be horizontally centered. - The
JustifyContent
property is set toSpaceEvenly
, which allocates all leftover vertical space equally between all the items, and above the first item, and below the last item.
For more information, see Xamarin.Forms FlexLayout.
RelativeLayout
A RelativeLayout
is used to position and size elements relative to properties of the layout or sibling elements. By default, an element is positioned in the upper left corner of the layout. A RelativeLayout
can be used to create UIs that scale proportionally across device sizes.
Within a RelativeLayout
, positions and sizes are specified as constraints. Constraints have Factor
and Constant
properties, which can be used to define positions and sizes as multiples (or fractions) of properties of other objects, plus a constant. In addition, constants can be negative.
Note
A RelativeLayout
supports positioning elements outside of its own bounds.
The following XAML shows how to arrange elements in a RelativeLayout
:
<RelativeLayout>
<BoxView Color="Blue"
HeightRequest="50"
WidthRequest="50"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0}" />
<BoxView Color="Red"
HeightRequest="50"
WidthRequest="50"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=.85}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0}" />
<BoxView x:Name="pole"
Color="Gray"
WidthRequest="15"
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=.75}"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=.45}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=.25}" />
<BoxView Color="Green"
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=.10, Constant=10}"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=.2, Constant=20}"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToView, ElementName=pole, Property=X, Constant=15}"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToView, ElementName=pole, Property=Y, Constant=0}" />
</RelativeLayout>
In this example, layout works as follows:
- The blue
BoxView
is given an explicit size of 50x50 device-independent units. It's placed in the upper left corner of the layout, which is the default position. - The red
BoxView
is given an explicit size of 50x50 device-independent units. It's placed in the upper right corner of the layout. - The gray
BoxView
is given an explicit width of 15 device-independent units, and it's height is set to be 75% of the height of its parent. - The green
BoxView
isn't given an explicit size. Its position is set relative to theBoxView
namedpole
.
Warning
Avoid using a RelativeLayout
whenever possible. It will result in the CPU having to perform significantly more work.
For more information, see Xamarin.Forms RelativeLayout.
AbsoluteLayout
An AbsoluteLayout
is used to position and size elements using explicit values, or values relative to the size of the layout. The position is specified by the upper-left corner of the child relative to the upper-left corner of the AbsoluteLayout
.
An AbsoluteLayout
should be regarded as a special-purpose layout to be used only when you can impose a size on children, or when the element's size doesn't affect the positioning of other children. A standard use of this layout is to create an overlay, which covers the page with other controls, perhaps to protect the user from interacting with the normal controls on the page.
Important
The HorizontalOptions
and VerticalOptions
properties have no effect on children of an AbsoluteLayout
.
Within an AbsoluteLayout
, the AbsoluteLayout.LayoutBounds
attached property is used to specify the horizontal position, vertical position, width and height of an element. In addition, the AbsoluteLayout.LayoutFlags
attached property specifies how the layout bounds will be interpreted.
The following XAML shows how to arrange elements in an AbsoluteLayout
:
<AbsoluteLayout Margin="40">
<BoxView Color="Red"
AbsoluteLayout.LayoutFlags="PositionProportional"
AbsoluteLayout.LayoutBounds="0.5, 0, 100, 100"
Rotation="30" />
<BoxView Color="Green"
AbsoluteLayout.LayoutFlags="PositionProportional"
AbsoluteLayout.LayoutBounds="0.5, 0, 100, 100"
Rotation="60" />
<BoxView Color="Blue"
AbsoluteLayout.LayoutFlags="PositionProportional"
AbsoluteLayout.LayoutBounds="0.5, 0, 100, 100" />
</AbsoluteLayout>
In this example, layout works as follows:
- Each
BoxView
is given an explicit size of 100x100, and is displayed in the same position, horizontally centered. - The red
BoxView
is rotated 30 degrees, and the greenBoxView
is rotated 60 degrees. - On each
BoxView
, theAbsoluteLayout.LayoutFlags
attached property is set toPositionProportional
, indicating that the position is proportional to the remaining space after width and height are accounted for.
Caution
Avoid using the AbsoluteLayout.AutoSize
property whenever possible, as it will cause the layout engine to perform additional layout calculations.
For more information, see Xamarin.Forms AbsoluteLayout.
Input transparency
Each visual element has an InputTransparent
property that's used to define whether the element receives input. Its default value is false
, ensuring that the element receives input.
When this property is set on a layout class, its value transfers to child elements. Therefore, setting the InputTransparent
property to true
on a layout class will result in all elements within the layout not receiving input.
Layout performance
To obtain the best possible layout performance, follow the guidelines at Optimize layout performance.
In addition, page rendering performance can also be improved by using layout compression, which removes specified layouts from the visual tree. For more information, see Layout compression.