Layouts
.NET Multi-platform App UI (.NET MAUI) 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.
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://schemas.microsoft.com/dotnet/2021/maui"
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.
For more information, see StackLayout.
HorizontalStackLayout
A HorizontalStackLayout organizes child views in a one-dimensional horizontal stack, and is a more performant alternative to a StackLayout. HorizontalStackLayout is typically used to arrange a subsection of the UI on a page.
The following XAML shows how to create a HorizontalStackLayout containing different child views:
<HorizontalStackLayout Margin="20">
<Rectangle Fill="Red"
HeightRequest="30"
WidthRequest="30" />
<Label Text="Red"
FontSize="18" />
</HorizontalStackLayout>
In a HorizontalStackLayout, if an element's size is not explicitly set, it expands to fill the available height.
For more information, see HorizontalStackLayout.
VerticalStackLayout
A VerticalStackLayout organizes child views in a one-dimensional vertical stack, and is a more performant alternative to a StackLayout. VerticalStackLayout is typically used to arrange a subsection of the UI on a page.
The following XAML shows how to create a VerticalStackLayout containing three Label objects:
<VerticalStackLayout Margin="20,35,20,25">
<Label Text="The VericalStackLayout has its Margin property set, to control the rendering position of the VerticalStackLayout." />
<Label Text="The Padding property can be set to specify the distance between the VerticalStackLayout and its children." />
<Label Text="The Spacing property can be set to specify the distance between views in the VerticalStackLayout." />
</VerticalStackLayout>
In a VerticalStackLayout, if an element's size is not explicitly set, it expands to fill the available width.
For more information, see VerticalStackLayout.
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.
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 first Label.
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 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 the FlexLayout 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 FlexLayout.
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 green BoxView is rotated 60 degrees.
- On each BoxView, the
AbsoluteLayout.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 AbsoluteLayout.
BindableLayout
A BindableLayout enables any layout class that derives from the Layout class to generate its content by binding to a collection of items, with the option to set the appearance of each item with a DataTemplate.
A bindable layout is populated with data by setting its ItemsSource
property to any collection that implements IEnumerable
, and attaching it to a Layout-derived class. The appearance of each item in the bindable layout can be defined by setting the BindableLayout.ItemTemplate
attached property to a DataTemplate.
The following XAML shows how to bind a StackLayout to a collection of items, and define their appearance with a DataTemplate:
<StackLayout BindableLayout.ItemsSource="{Binding User.TopFollowers}"
Orientation="Horizontal">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}"
Aspect="AspectFill"
WidthRequest="44"
HeightRequest="44" />
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
Bindable layouts should only be used when the collection of items to be displayed is small, and scrolling and selection isn't required.
For more information, see BindableLayout.
Custom layouts
In .NET MAUI, the layout classes derive from the abstract Layout class. This class delegates cross-platform layout and measurement to a layout manager class. Each layout manager class implements the ILayoutManager interface, which specifies that Measure and ArrangeChildren implementations must be provided:
- The Measure implementation calls IView.Measure on each view in the layout, and returns the total size of the layout given the constraints.
- The ArrangeChildren implementation determines where each view should be placed within the bounds of the layout, and calls Arrange on each view with its appropriate bounds. The return value is the actual size of the layout.
.NET MAUI's layouts have pre-defined layout managers to handle their layout. However, sometimes it's necessary to organize page content using a layout that isn't provided by .NET MAUI. This can be achieved by writing your own custom layout. For more information, see Custom layouts.
Input transparency
Each visual element has an InputTransparent
bindable property that's used to define whether the element can receive input. Its default value is false
, ensuring that the element can receive input. When this property is true
on an element, the element won't receive any input. Instead, input will be passed to any elements that are visually behind the element.
The Layout class, from which all layouts derive, has a CascadeInputTransparent
bindable property that controls whether child elements inherit the input transparency of the layout. Its default value is true
, ensuring that setting the InputTransparent
property to true
on a layout class will result in all elements within the layout not receiving any input.
.NET MAUI