You can manage a child component’s
size and position simultaneously by using constraint-based layout,
or by using constraint rows and columns. Constraint-based layout
lets you anchor the sides or center of a component to positions relative
to the viewable region of the component’s container. The viewable region is
the part of the component that is being displayed, and it can contain
child controls, text, images, or other contents.
Constraint rows and columns let you subdivide a container into
vertical and horizontal constraint regions to control the size and
positioning of child components with respect to each other and within
the parent container.
Creating a constraint-based layout
You can use constraint-based layout to determine the position
and size of the immediate children of any container that supports
absolute positioning. With constraint-based layout, you can do the
following:
Anchor one or more edges of a component at a pixel offset
from the corresponding edge of its container’s viewable region.
The anchored child edge stays at the same distance from the parent
edge when the container resizes. If you anchor both edges in a dimension,
such as top and bottom, the component resizes if the container resizes.
Anchor the child’s horizontal or vertical center (or both)
at a pixel offset from the center of the container’s viewable region.
The child does not resize in the specified dimension unless you
also use percentage-based sizing.
Anchor the baseline of a component at a pixel offset from
the top edge of its parent container.
You can specify a constraint-based layout for any Flex framework
component (that is, any component that extends the UIComponent class).
The following rules specify how to position and size components
by using constraint-based layout:
Place the component in any Spark container that uses
BasicLayout, in a MX Canvas container, or in a MX Application or
MX Panel container with the layout property set
to absolute.
Specify the constraints by using the baseline, top, bottom, left, right, horizontalCenter,
or verticalCenter properties of UIComponent and
GraphicElement.
Note: In previous releases of Flex, the baseline,
top, bottom, left, right, horizontalCenter, or verticalCenter properties
were implemented as styles. You can still use them as styles in
this release.
The top, bottom, left,
and right properties specify the distances between
the component sides and the corresponding container sides.
The baseline constraint
specifies the distance between the baseline position of a component
and the upper edge of its parent container. Every component calculates
its baseline position as the y-coordinate of the baseline of the
first line of text of the component. The baseline of a UIComponent object
that does not contain any text is calculated as if the UIComponent object
contained a UITextField object that uses the component's styles,
and the top of the UITextField object coincides with the component's
top.
The horizontalCenter and verticalCenter properties
specify distance between the component’s center point and the container’s
center, in the specified direction; a negative number moves the
component left or up from the center.
The following example
anchors the Form control’s left and right sides 20 pixels from its
container’s sides:
<mx:Form id="myForm" left="20" right="20"/>
Do not specify a top or bottom property
with a verticalCenter property; the verticalCenter value
overrides the other properties. Similarly, do not specify a left or right property
with a horizontalCenter property.
A size determined by constraint-based layout overrides any
explicit or percentage-based size specifications. If you specify left and right constraints,
for example, the resulting constraint-based width overrides any width
set by a width or percentWidth property.
Precedence rules for constraint-based components
If you specify a single edge constraint (left, right, top, or bottom) without
any other sizing or positioning parameter, the component size is
the default size and its position is determined by the constraint
value. If you specify a size parameter (width or height), the size
is determined by that parameter.
If you specify a pair of constraints (left-right or top-bottom),
the size and position of the component is determined by those constraint
values. If you also specify a center constraint (horizontalCenter or verticalCenter),
the size of the component is calculated from the edge constraints
and its position is determined by the center constraint value.
Component size determined by a pair of constraint-based layout
properties (left-right or top-bottom)
overrides any explicit or percentage-based size specifications.
For example, if you specify both left and right constraints,
the calculated constraint-based width overrides the width set by a width or percentWidth property.
Edge constraints override baseline constraints.
Example: Using constraint-based layout for a form
The following example code shows how you can use constraint-based
layout for a form. In this example, the Form control uses a constraint-based
layout to position its top just inside the canvas padding. The form
left and right edges are 20 pixels from the outer SkinnableContainer
container’s left and right edges. The second, inner, SkinnableContainer
that contains the buttons uses a constraint-based layout to place
itself 20 pixels from the right edge and 10 pixels from the bottom
edge of the outer SkinnableContainer container.
If you change the size of your browser, stand-alone Flash Player,
or AIR application, you can see the effects of dynamically resizing
the application container on the Form layout. The form and the buttons
overlap as the application grows smaller, for example.
<?xml version="1.0"?>
<!-- components\ConstraintLayout.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<s:SkinnableContainer width="100%" height="100%">
<!-- Anchor the top of the form at the top of the canvas.
Anchor the form sides 20 pixels from the canvas sides. -->
<s:Form id="myForm"
backgroundColor="#DDDDDD"
top="0"
left="20"
right="20">
<s:FormItem label="Product:" width="100%">
<!-- Specify a fixed width to keep the ComboBox control from
resizing as you change the application size. -->
<s:ComboBox width="200"/>
</s:FormItem>
<s:FormItem label="User" width="100%">
<s:ComboBox width="200"/>
</s:FormItem>
<s:FormItem label="Date">
<mx:DateField/>
</s:FormItem>
<s:FormItem width="100%"
label="Hours:">
<s:TextInput width="75"/>
</s:FormItem>
<s:FormItem width="100%"
label="Minutes:">
<s:TextInput width="75"/>
</s:FormItem>
</s:Form>
<!-- Anchor the box with the buttons 20 pixels from the canvas
right edge and 10 pixels from the bottom. -->
<s:SkinnableContainer id="okCancelBox"
right="20"
bottom="10">
<s:layout>
<s:HorizontalLayout/>
</s:layout>
<s:Button label="OK"/>
<s:Button label="Cancel"/>
</s:SkinnableContainer>
</s:SkinnableContainer>
</s:Application>
The executing SWF file for the previous example is shown below:
Using constraint rows and columns with MX containers and the Spark FormLayout class
You can subdivide a container that supports absolute positioning
into vertical and horizontal constraint regions to control the size
and positioning of child components with respect to each other,
or with respect to the parent container.
Note: Constraint rows and columns are only supported by the MX
containers, and the Spark FormLayout class.
You define the horizontal and vertical constraint regions of
a container by using the constraintRows and constraintColumns properties.
These properties contain Arrays of constraint objects that partition
the container horizontally (ConstraintColumn objects) and vertically
(ConstraintRow objects). ConstraintRow objects are laid out in the
order they are defined, from top to bottom in their container; ConstraintColumn
objects are laid out from left to right in the order they are defined.
The following example shows a Canvas container
partitioned into two vertical regions and two horizontal regions.
The first constraint column occupies 212 pixels from the leftmost
edge of the Canvas. The second constraint column occupies
100% of the remaining Canvas width. The rows in this example occupy 80%
and 20% of the Canvas container’s height from top to bottom, respectively.
<?xml version="1.0"?>
<!-- constraints\BasicRowColumn.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<mx:Canvas>
<mx:constraintColumns>
<mx:ConstraintColumn id="col1" width="212"/>
<mx:ConstraintColumn id="col2" width="100%"/>
</mx:constraintColumns>
<mx:constraintRows>
<mx:ConstraintRow id="row1" height="80%"/>
<mx:ConstraintRow id="row2" height="20%"/>
</mx:constraintRows>
<!-- Position child components based on
the constraint columns and rows. -->
</mx:Canvas>
</s:Application>
The executing SWF file for the previous example is shown below:
Constraint rows and columns do not have to occupy 100% of the
available area in a container. The following example shows a single
constraint column that occupies 20% of the Canvas width; 80% of
the container is unallocated:
<?xml version="1.0"?>
<!-- constraints\BasicColumn_20Percent.mxml -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:s="library://ns.adobe.com/flex/spark">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<mx:Canvas>
<mx:constraintColumns>
<mx:ConstraintColumn id="col1" width="20%"/>
</mx:constraintColumns>
</mx:Canvas>
<!-- Position child components based on
the constraint column. -->
</s:Application>
Creating constraint rows and columns
Constraint columns and rows
have three sizing options: fixed, percent, and content. These options
dictate the amount of space that the constraint region occupies
in the container. As child components are added to or removed from the
parent container, the space allocated to each ConstraintColumn and ConstraintRow
instance is computed according to its sizing option.
Fixed size means the space allocated to the constraint
region is a fixed pixel size. In the following example, you set
the fixed with of a ConstraintColumn instance to 100 pixels:
<mx:ConstraintColumn id="col1" width="100"/>
As
the parent container grows or shrinks, the ConstraintColumn instance remains
100 pixels wide.
Percent size means that the space allocated to the
constraint row or column is calculated as a percentage of the space
remaining in the parent container after the space allocated to fixed
and content size child objects has been deducted from the available
space.
In the following example, you set the width of a ConstraintColumn
instance to 80%:
<mx:ConstraintColumn id="col1" width="80%"/>
As
the parent container grows or shrinks, the ConstraintColumn always
takes up 80% of the available width.
A best practice in specifying
percent constraints is to ensure that the sum of all percent constraints
is less than or equal to 100%. However, if the total value of percent
specifications is greater than 100%, the actual allocated percentages are
calculated so that the proportional values for all constraints total
100%. For example, if the percentages for two constraint objects
are specified as 100% and 50%, the values are adjusted to 66.6%
and 33.3% (two-thirds for the first value and one-third for the
second).
Content size (default) means that the space allocated
to the region is dictated by the size of the child objects in that
space. As the size of the content changes, so does the size of the
region. Content sizing is the default when you do not specify either
fixed or percentage sizing parameters.
In the following example,
you specify content size by omitting any explicit width setting:
<mx:ConstraintColumn id="col1"/>
The
width of this ConstraintColumn is determined by the width of its
largest child. When children span multiple content sized constraint
rows or constraint columns, Flex divides the space consumed by the
children among the rows and columns.
For the ConstraintColumn
class, you can also use the maxWidth and minWidth properties
to limit the width of the column. For the ConstraintRow class, you
can use the maxHeight and minHeight properties
to limit the height of the row. Minimum and maximum sizes for constraint
columns and rows limit how much the constraint regions grow or shrink
when you resize their parent containers. If the parent container
with a constraint region shrinks to less than the minimum size for
that region when you resize the container, scroll bars appear to
show clipped content.
Note: Minimum and maximum
limits are only applicable to percentage and content sized constraint
regions. For fixed size constraint regions, minimum and maximum values,
if specified, are ignored.
Positioning child components based on constraint rows and constraint columns
Anchor
a child component to a constraint row or constraint column by prepending
the constraint region’s ID to any of the child’s constraint parameters. For
example, if the ID of a ConstraintColumn is "col1", you can specify
a set of child constraints as left="col1:10", right="col1:30", horizontalCenter="col1:0".
If
you do not qualify constraint parameters (left, right, top,
and bottom) a constraint region ID, the component
is constrained relative to the edges of its parent container. Components
can occupy a single constraint region (row or column) or can span
multiple regions.
The following example uses constraint rows
and constraint columns to position three Button controls in a Canvas
container:
The executing SWF file for the previous example is shown below:
While you can specify any combination
of qualified and unqualified constraints, some constraint properties
may be overridden. The priority of sizing and positioning constraints
are as follows:
Center constraint specifications override
all other constraint values when determining the position of a control.
Next, left edge and top positions are determined.
Finally, right edge and bottom positions are calculated to
best fit the component.
The following table defines
the behavior of constrained components when they are contained in
a single constraint region. Edge 1 is the first specified
edge constraint for a child component (left, right, top,
or bottom). Edge 2 is the second specified
edge constraint of a pair (left and right, top and bottom). Size is
an explicit size for a child component (width, height). Center is
the positioning constraint to center the child object (horizontalCenter or verticalCenter).
Constraint Parameters
Behavior
Edge 1
Edge 2
Size
Center
Size
Position
x
Default component size
Relative to specified edge constraint
x
x
Calculated from specified edge constraints
Relative to specified edge constraints
x
x
x
Determined from specified edge constraints.
Explicit size is overridden
Relative to specified edge constraints
x
x
Specified size
Relative to specified edge
x
x
Default component size
Centered in constraint region; edge constraint
is ignored
x
x
x
Calculated from edge constraints
Centered in constraint region
x
x
x
Explicit size
Centered in constraint region; single edge
constraint is ignored
x
Default size of component
Centered in constraint region
Using Baseline property
The baseline property
defines the offset between the baseline defined by the constraint
row (or the top of the container) and the baseline position of the element.
The
baseline property can be specified as a number or can be specified
with respect to the max ascent of the row.
If the baseline
value on a row is only a number, the elements contained by the row
are positioned that many pixels below the top of the container.
If the baseline value is defined with respect to the max ascent
of the row, then it is defined in the format: "maxAscent:x". The
default value is "maxAscent:0".
The following code example
defines four labels in a group, where each label is constrained
with a baseline alignment to row1 and maxAscent:5.