LayoutOptions in Xamarin.Forms

From my experience working with Xamarin.Forms layouts, I found using LayoutOptions to be rather confusing. I would throw them around if and when I thought they were appropriate. And more often than not, they produced inaccurate results. While the documentation provided on the Xamarin.Forms website was somewhat helpful, I still made mistakes and used a lot of guess work and reran my code multiple times to come up with the layouts I desired.

This post aims at clearing up some of the confusion when dealing with LayoutOptions. If you have been using Xamarin.Forms for sometime, the main takeaways are

  • Default LayoutOptions values on Xamarin.Forms Layouts, Views and Controls are Fill except for RelativeLayout where the values are FillAndExpand
  • StackLayouts position their child views according to the order in which they are added to the StackLayout, hence, LayoutOptions values without the -AndExpand suffix are ignored when used for setting LayoutOptions properties in the direction of the containing StackLayout
  • The -AndExpand suffix is redundant when used for setting LayoutOptions properties in the opposite direction of the containing StackLayout. “AndExpand” functions to allocate extra space in the StackLayout among its children and since there’s only one child in the opposite direction of the StackLayout, the suffix serves no purpose

HorizontalOptions and VerticalOptions are properties on Xamarin.Forms Layouts, Views and Controls. Their usage allows for a fairly simple way to position view elements within parent layouts without needing to manipulate other property values. However, not knowing what these values represent and when they are applicable can slow down the layout creation process and consume unnecessary memory if the LayoutOptions set is redundant.

The LayoutOptions values available are

Start StartAndExpand
Center CenterAndExpand
End EndAndExpand
Fill FillAndExpand

Firstly, it is important to note that the default values for LayoutOptions on Xamarin.Forms Layouts, Views and Controls are Fill except for RelativeLayout where the default values are FillAndExpand. This may seem odd but it’s clear in the source code.

Default values for HorizontalOptions and VerticalOptions on Layouts, Views and Controls are Fill except for Relative Layouts where the default values are FillAndExpand

While HorizontalOptions and VerticalOptions properties can be applied on most Xamarin.Forms view types, they are only often useful when used on child views within StackLayouts and sometimes useful when used on child views within Grids. Altering LayoutOptions values for child views within AbsoluteLayouts and RelativeLayouts does not change the original position of the child view. Both these parent layouts have their own layout bounds properties that should be set on their child views. Therefore, this post will only elaborate using LayoutOptions on child views within StackLayouts and a following post will elaborate on using LayoutOptions on child views within Grids.

This post will be broken down into two sections. The first one will discuss using LayoutOptions in the direction of the containing StackLayout orientation meaning setting

  1. VerticalOptions properties on child views within vertical StackLayouts and
  2. HorizontalOptions properties on child views within horizontal StackLayouts

The second part will discuss using LayoutOptions in the opposite direction of the containing StackLayout orientation meaning using

  1. HorizontalOptions properties on child views within vertical StackLayouts and
  2. VerticalOptions properties on child views within horizontal StackLayouts.
LayoutOptions in same direction as parent StackLayout Orientation

The first four values (the ones without the -AndExpand suffix) position child views within StackLayouts according to the meaning of their names. These values are ignored when setting LayoutOptions in the direction of the containing StackLayout Orientation. This is because, in a vertical StackLayout for example, child views will be ordered vertically according to the order in which they are added to the Stack Layout so setting VerticalOptions to any of these values is redundant. The same rule applies for horizontal StackLayouts. Child views within horizontal StackLayouts are ordered horizontally in the order in which they are added to the StackLayout so setting HorizontalOptions on child views to Start, Center, End or Fill would be irrelevant.

However, there is an exception. If the child view is a RelativeLayout, with default LayoutOptions values of FillAndExpand, as stated above, its size will be altered vertically if it’s contained within a vertical StackLayout and horizontally if is contained within a horizontal StackLayout (this will be discussed in further detail below). So to override this behavior, a RelativeLayout’s  LayoutOptions property should be set to Fill.

 LayoutOptions values Start, Center, End and Fill are ignored when used for setting LayoutOptions properties in the direction of the containing StackLayout orientation (unless child view is RelativeLayout)

While LayoutOptions values without the -AndExpand suffix are ignored, LayoutOptions values with the -AndExpand suffix are relevant when applied on LayoutOptions values in the direction of the containing StackLayout. These values expand the space allocated for child view in the direction of the parent StackLayout orientation.

So for instance, setting VerticalOptions to StartAndExpand on a view within a vertical StackLayout adds some space below the child view. Setting VerticalOptions to CenterAndExpand adds some space above and below the child view, End adds some space above the child view and Fill stretches the child view vertically so it fills the remaining space available in the StackLayout.

The extra space allocated to the child views are measured by dividing the total extra vertical space available in the StackLayout by the number of views that have set their VerticalOptions to the -AndExpand suffix. One important thing to note is that these VerticalOptions values, similar to the values without the -AndExpand suffix, don’t affect how child views are ordered vertically in a vertical StackLayout.

*StackLayout’s BackgroundColor = Yellow, StackLayout’s Spacing = 0, Labels’ BackgroundColor = Blue, BoxViews in between labels to highlight space allocations

The same principles apply when setting HorizontalOptions values with the -AndExpand suffix on child views within horizontal StackLayouts. Setting HorizontalOptions to StartAndExpand on a view within a horizontal StackLayout adds some space to the right of the child view. Setting HorizontalOptions to CenterAndExpand adds some space to the left and right of the child view, EndAndExpand adds some space to the left of the child view and FillAndExpand stretches the child view horizontally so it fills the remaining space available in the StackLayout.

The extra space is apportioned by dividing the horizontal extra space available in the parent StackLayout by the number of child views that have set their HorizontalOptions values to a value with the -AndExpand suffix. Again these HorizontalOptions values similar to the values without the -AndExpand suffix don’t affect how child views are ordered horizontally in a horizontal StackLayout.

*StackLayout’s BackgroundColor = Yellow, StackLayout’s Spacing = 0, Labels’ BackgroundColor = Blue, BoxViews in between labels to highlight space allocations

LayoutOptions in opposite direction as parent StackLayout Orientation

Let’s again start with the first four values, the ones without the -AndExpand suffix. These values while ignored when applied to LayoutOptions in the direction of the StackLayout orientation, are in fact relevant when applied to LayoutOptions in the opposite direction of the StackLayout orientation.

So for instance if HorizontalOptions is set to Start on a view within a vertical StackLayout, the view will be positioned at the left border of the StackLayout. Whereas setting HorizontalOptions to Center will horizontally center the view within the StackLayout, setting HorizontalOptions to End will position the view to the right border of the StackLayout and Fill(default) will display the view so that it fills the width of the StackLayout.

*StackLayout’s BackgroundColor = Yellow, Labels’ BackgroundColor = Blue

The same rules apply to child views within horizontal StackLayouts. When setting VerticalOptions to Start on a view within a horizontal StackLayout, the view will be positioned at the top border of the Stack Layout. While setting VerticalOptions to Center vertically centers the view within the StackLayout, setting VerticalOptions to End will position the view at the bottom of the StackLayout and Fill(default) will display the view so that it fills the height of the StackLayout.

*StackLayout’s BackgroundColor = Yellow, Labels’ BackgroundColor = Blue

Now let’s move on to the values with the -AndExpand suffix. These values when set on LayoutOptions in the opposite direction of the containing StackLayout orientation will display the views the same manner as LayoutOptions without the -AndExpand suffix would (the suffix is ignored). 

This is because, in a vertical StackLayout for instance, adding the -AndExpand suffix to a child view’s HorizontalOptions value is irrelevant because the StackLayout can’t necessarily allocate extra space to the view horizontally because there’s only one child in each row of a vertical StackLayout. I guess “AndExpand” is not the right suffix. It should be “AndAllocateExtra”. Reallocation of extra space can only occur if extra space can be shared among multiple child views as discussed above. So whether or not you add the -AndExpand suffix the view will be displayed the same way as if you did not add it.

The same is true when setting VerticalOptions values on horizontal StackLayouts. There’s only one child view in every column of a horizontal StackLayout. So it is not possible for the StackLayout to reallocate space vertically and therefore setting the VerticalOptions value to one with or without the -AndExpand suffix would produce the same result.

The -AndExpand suffix is redundant when used for setting LayoutOptions properties in the opposite direction of the containing StackLayout orientation

Summary table:

VerticalOptions on child view of Vertical StackLayout HorizontalOptions on child view of Horizontal StackLayout HorizontalOptions on child view of Vertical StackLayout VerticalOptions on child view of Horizontal StackLayout
FillIgnoredIgnoredFills width of StackLayoutFills height of StackLayout
Start IgnoredIgnoredPositions view at the left border of StackLayoutPositions view at the top of StackLayout
CenterIgnoredIgnoredCenters view horizontally within StackLayoutCenters view vertically within StackLayout
EndIgnoredIgnoredPositions view at the right border of StackLayoutPositions view at the bottom of StackLayout
FillAndExpandStretches view vertically so it fills the remaining space allocated to itStretches view horizontally so it fills the remaining space allocated to itSame as using FillSame as using Fill
StartAndExpandAdds space to the bottom of the viewAdds space to the right of the viewSame as using StartSame as using Start
CenterAndExpandAdds space to the top and bottom of the viewAdds space to the right and left of the viewSame as using Center
Same as using Center
EndAndExpandAdds space to the top of the viewAdds space to the left of the viewSame as using EndSame as using End

Citations

  1. https://developer.xamarin.com/guides/xamarin-forms/deployment-testing/performance/
  2. https://developer.xamarin.com/guides/xamarin-forms/user-interface/layouts/layout-options/
  3. https://github.com/xamarin/Xamarin.Forms/blob/dfeb9f7f9122279101d3d37572629ba1b8d4192a/Xamarin.Forms.Core/RelativeLayout.cs#L29.

Author

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.