Summary of Chapter 14. Absolute layout
Note
This book was published in the spring of 2016, and has not been updated since then. There is much in the book that remains valuable, but some of the material is outdated, and some topics are no longer entirely correct or complete.
Like StackLayout
, AbsoluteLayout
derives from Layout<View>
and inherits a Children
property. AbsoluteLayout
implements a layout system that requires the programmer to specify the positions of its children and, optionally, their size. The position is specified by the upper-left corner of the child relative to the upper-left corner of the AbsoluteLayout
in device-independent units. AbsoluteLayout
also implements a proportional positioning and sizing feature.
AbsoluteLayout
should be regarded as a special-purpose layout system to be used only when the programmer can impose a size on the children (for example, BoxView
elements) or when the element's size doesn't affect the positioning of other children. The HorizontalOptions
and VerticalOptions
properties have no effect on children of an AbsoluteLayout
.
This chapter also introduces the important feature of attached bindable properties that allow properties defined in one class (in this case AbsoluteLayout
) to be attached to another class (a child of the AbsoluteLayout
).
AbsoluteLayout in code
You can add a child to the Children
collection of an AbsoluteLayout
using the standard Add
method, but AbsoluteLayout
also provides an extended Add
method that lets you specify a Rectangle
. Another Add
method requires only a Point
, in which case the child is unconstrained and sizes itself.
You can create a Rectangle
value with a constructor that requires four values — the first two indicating the position of the upper-left corner of the child relative to its parent, and the second two indicating the child's size. Or you can use a constructor that requires a Point
and a Size
value.
These Add
methods are demonstrated in AbsoluteDemo, which positions BoxView
elements using Rectangle
values, and a Label
element using just a Point
value.
The ChessboardFixed sample uses 32 BoxView
elements to create the chessboard pattern. The program gives the BoxView
elements a hard-coded size of 35 units square. The AbsoluteLayout
has its HorizontalOptions
and VerticalOptions
set to LayoutOptions.Center
, which causes the AbsoluteLayout
to have a total size of 280 units square.
Attached bindable properties
It is also possible to set the position and, optionally, the size of a child of an AbsoluteLayout
after it has been added to the Children
collection using the static method AbsoluteLayout.SetLayoutBounds
. The first argument is the child; the second is a Rectangle
object. You can specify that the child sizes itself horizontally and/or vertically by setting width and height values to the AbsoluteLayout.AutoSize
constant.
The ChessboardDynamic sample puts the AbsoluteLayout
in a ContentView
with a SizeChanged
handler to call AbsoluteLayout.SetLayoutBounds
on all the children to make them as large as possible.
The attached bindable property that AbsoluteLayout
defines is the static read-only field of type BindableProperty
named AbsoluteLayout.LayoutBoundsProperty
. The static AbsoluteLayout.SetLayoutBounds
method is implemented by calling SetValue
on the child with the AbsoluteLayout.LayoutBoundsProperty
. The child contains a dictionary in which the attached bindable property and its value are stored. During layout, the AbsoluteLayout
can obtain that value by calling AbsoluteLayout.GetLayoutBounds
, which is implemented with a GetValue
call.
Proportional sizing and positioning
AbsoluteLayout
implements a proportional sizing and positioning feature. The class defines a second attached bindable property, LayoutFlagsProperty
, with the related static methods AbsoluteLayout.SetLayoutFlags
and AbsoluteLayout.GetLayoutFlags
.
The argument to AbsoluteLayout.SetLayoutFlags
and the return value of AbsoluteLayout.GetLayoutFlags
is a value of type AbsoluteLayoutFlags
, an enumeration with the following members:
None
(equal to 0)XProportional
(1)YProportional
(2)PositionProportional
(3)WidthProportional
(4)HeightProportional
(8)SizeProportional
(12)All
(\xFFFFFFFF)
You can combine these with the C# bitwise OR operator.
With these flags set, certain properties of the Rectangle
layout bounds structure used to position and size the child are interpreted proportionally.
When the WidthProportional
flag is set, a Width
value of 1 means that the child is the same width as the AbsoluteLayout
. A similar approach is used for the height.
The proportional positioning takes the size into account. When the XProportional
flag is set, the X
property of the Rectangle
layout bounds is proportional. A value of 0 means that the child's left edge is positioned at the left edge of the AbsoluteLayout
, but a position of 1 means that the child's right edge is positioned at the right edge of the AbsoluteLayout
, not beyond the right edge of the AbsoluteLayout
as you might expect. An X
property of 0.5 centers the child horizontally in the AbsoluteLayout
.
The ChessboardProportional sample demonstrates the use of proportional sizing and positioning.
Working with proportional coordinates
Sometimes, it's easier to think of proportional positioning differently than how it's implemented in the AbsoluteLayout
. You might prefer to work with proportional coordinates where an X
property of 1 positions the child's left edge (rather than the right edge) against the right edge of the AbsoluteLayout
.
This alternative positioning scheme can be called "fractional child coordinates." You can convert from fractional child coordinates to the layout bounds required for AbsoluteLayout
using the following formulas:
layoutBounds.X = (fractionalChildCoordinate.X / (1 - layoutBounds.Width))
layoutBounds.Y = (fractionalChildCoordinate.Y / (1 - layoutBounds.Height))
The ProportionalCoordinateCalc sample demonstrates this.
AbsoluteLayout and XAML
You can use an AbsoluteLayout
in XAML and set the attached bindable properties on the children of an AbsoluteLayout
using attribute values of AbsoluteLayout.LayoutBounds
and AbsoluteLayout.LayoutFlags
. This is demonstrated in the AbsoluteXamlDemo and the ChessboardXaml samples. The latter program contains 32 BoxView
elements but uses an implicit Style
that includes the AbsoluteLayout.LayoutFlags
property to keep the markup down to a minimum.
An attribute in XAML that consists of a class name, a dot, and a property name is always an attached bindable property.
Overlays
You can use AbsoluteLayout
to construct an overlay, which covers the page with other controls, perhaps to protect the user from interacting with the normal controls on the page.
The SimpleOverlay sample demonstrates this technique, and also demonstrates the ProgressBar
, which displays the extent to which a program has completed a task.
Some fun
The DotMatrixClock sample displays the current time with a simulated 5x7 dot matrix display. Each dot is a BoxView
(there are 228 of them) sized and positioned on the AbsoluteLayout
.
The BouncingText program animates two Label
objects to bounce horizontally and vertically across the screen.