APL Container

A Container component displays multiple child items. The Container uses a subset of Flexbox/Yoga as the layout language.

Properties

The Container component has the following properties:

Property Type Default Styled Dynamic Description

alignItems

One of: stretch, center, start, end, baseline

stretch

Yes

Yes

Alignment for children in the cross-axis.

direction

One of: column, row, columnReverse, rowReverse

column

Yes

Yes

Direction in which to display the child components.

justifyContent

One of: start, end, center, spaceBetween, spaceAround

start

Yes

Yes

How to distribute free space when there is room on the main axis. Defaults to start.

numbered

boolean

false

No

No

When true, assign ordinal numbers to children. Defaults to false.

wrap

One of: noWrap, wrap, wrapReverse

noWrap

Yes

Yes

Determines how to wrap child components to multiple lines.

Unlike standard Flexbox containers, The APL Container component doesn't scroll. Place the Container within a ScrollView to create a scrolling component.

When the Container is the source or target of an event, the following values are reported in event.source or event.target:

{
  // Container-specific values
  "type": "Container",

  // General component values
  "bind": Map,         // Access to component data-binding context
  "checked": Boolean,  // Checked state
  "disabled": Boolean, // Disabled state
  "focused": Boolean,  // Focused state
  "height": Number,    // Height of the component, in dp (includes the padding)
  "id": ID,            // ID of the component
  "opacity": Number,   // Opacity of the component [0-1]
  "pressed": Boolean,  // Pressed state
  "uid": UID,          // Runtime-generated unique ID of the component
  "width": Number      // Width of the component, in dp (includes the padding)
}

layoutDirection component property

The component layoutDirection property determines the direction to lay out the Container child components. An APL Container follows the same rules as the Yoga layoutDirection property.

The component layoutDirection property determines the override behavior of the following properties that control positioning for the Container children:

  • left and right
  • start and end

alignItems

The Flexbox specification for how to align the child components in the cross-axis of the container. Defaults to stretch.

direction

The direction of layout in the container. Defaults to column. The direction property can take the following values:

Type Description

column

Lay out the child components in a vertical column (Default).

row

Lay out the child components in a horizontal row.

columnReverse

Lay out the child components in a vertical column, but start from the opposite side

rowReverse

Lay out the child components in a horizontal row , but start from the opposite side

The layoutDirection property determines the horizontal direction of the items when direction is row. For example, when layoutDirection is RTL and direction is row, the child items start on the right and display to the left.

justifyContent

The Flexbox specification for how to distribute free space when there is room on the main axis. This property applies when the container is larger than the size of its children. Defaults to start.

numbered

When true, set the data-binding ordinal for each of the items in the Container. The ordinals start with "1" and increment by one unless the numbering property in a child is set to "skip" or "reset". Note that the firstItem and lastItem properties don't participate in ordinal numbering. Defaults to false.

wrap

The Flexbox wrapping behavior of the children. The wrap property takes the following values:

Type Description

noWrap

The Container lays out the children in a single line on the main axis. The Container might overflow. (Default)

wrap

The child components can break into multiple lines.

wrapReverse

The child components can break into multiple lines, but start from the opposite side.

Multichild properties

A Container is a multi-child component. The Container inherits all of the multi-child properties.

Container child component properties

The child components of a Container have additional properties to control positioning within the parent container.

Property Type Default Styled Dynamic Description

alignSelf

auto, start, end, center, baseline, stretch

auto

Yes

Yes

Cross-axis layout position. Defaults to auto.

bottom

Dimension

auto

Yes

Yes

Specifies the position offset of the bottom edge.

end

Dimension

none

Yes

Yes

Position offset of the end edge. The end edge is either the left or right side of the component, depending on the layoutDirection for the component.

grow

Number

0

Yes

Yes

When positive, proportionally stretch this component if there is extra space in the Container. Defaults to 0.

left

Dimension

auto

Yes

Yes

Specifies the position offset of the left edge.

numbering

normal, skip, reset

normal

No

No

Control ordinal numbering of the next child. Defaults to normal.

position

relative, absolute, sticky

relative

Yes

Yes

Adjust the position of the child component. When absolute, take this component out of the normal layout ordering and position it relative to the parent container. Defaults to 'relative'.

right

Dimension

auto

Yes

Yes

Specifies the position offset of the right edge.

shrink

Number

0

Yes

Yes

When positive, proportionally shrink this component if there is not enough space in the Container. Defaults to 0.

spacing

Absolute Dimension

0

Yes

Yes

Additional space to add between this component and the previous component in the layout. Defaults to 0.

start

Dimension

none

Yes

Yes

Position offset of the starting edge. The starting edge is either the left or right side of the component, depending on the layoutDirection for the component.

top

Dimension

auto

Yes

Yes

Specifies the position offset of the top edge.

alignSelf

Overrides the alignItems property for this child component.

position, bottom, left, right, top

The position property determines how the bottom, left, right, and top properties adjust the position of the child component from its "standard" location.

The start and end properties also override left and right based on the layoutDirection for the ``Container`.

Absolute positioning

When position is absolute, the child component is taken out of the normal layout ordering for the container and instead positioned absolutely relative to the parent. The top, bottom, left, and right properties are dimensional offsets from the sides of the parent container. The padding of the parent container is ignored for an absolutely positioned child component.

In an "absolute"-positioned element where the size of the element is fixed, the top property overrides the bottom property when both are set. The left and right properties depend on the layoutDirection property of the parent container:

  • Parent container's layoutDirection is set to "LTR" – if left is set, the right property is ignored. If neither position properties are set, the element is positioned at the top-left of the parent container.
  • Parent container's layoutDirection is set to "RTL" – if right is set, the left property is ignored. If neither position properties are set, the element is positioned at the top-right of the parent container.

The following example shows a component that sets all four position properties.

{
    "position": "absolute",
    "width": 100,
    "height": 100,
    "top": 5,
    "bottom": 5,
    "left": 5,
    "right": 5
}

When layoutDirection for the Container is LTR, this component is positioned 5 units from the top-left of the parent container. The values for bottom and right are ignored because top and left are set.

When layoutDirection for this Container is RTL, this component is positioned 5 units from the top-right of the parent container. The values for bottom and left are ignored because top and right are set.

Relative positioning

When position is relative, the bottom, left, right, and top properties are dimensional offsets from the "normal" position of the child, relative to the other components in the Container. When top has a value, the bottom property is ignored. The left and right properties depend on the layoutDirection property of the parent container:

  • Parent container's layoutDirection is set to "LTR" – if left is set, the right property is ignored.
  • Parent container's layoutDirection is set to "RTL" – if right is set, the left property is ignored.

The following example shows a component that sets top, bottom, and right.

{
    "position": "relative",
    "top": 5,
    "bottom": 20,
    "right": 5
}

When layoutDirection for the Container is LTR, this component is positioned 5 units down and 5 units to the left of its normal position relative to the other child components. The bottom and right properties are ignored.

When layoutDirection for the Container is RTL, this component displays 5 units down and 5 units to the right of its normal position relative to the other child components. The bottom and left properties are ignored.

Sticky positioning

When position is relative, the bottom, left, right, and top properties are dimensional offsets calculated in reference to the nearest scrollable ancestor component. This position "sticks" the component to the ancestor component.

For a sticky component, the top and bottom properties represent insets from the respective edges of the nearest vertical scrollable component. The left and right properties represent insets from the edges of the nearest horizontal scrollable. These properties define the "sticky view" rectangle used to constrain the component’s position.

If the sticky view rectangle size in any axis is less than the size of the default bounds of the sticky component in that axis, then the effective end-edge inset in the affected axis is reduced (possibly becoming negative) to bring the sticky view rectangle’s size up to the size of the default bounds in that axis.

For example:

Assume the nearest vertical scrollable item is 300px tall and the sticky component has a default bounds of 200px tall. The top property is 20px. This means that the top edge inset of the nearest ancestor is 20px and the bottom edge inset is 0px. The sticky view rectangle is therefore 280px tall.

However, if the nearest vertical scrollable item is 100px tall, then the effective bottom edge inset becomes -120px. This results in a sticky view rectangle that's 200px tall.

For each side of the component, if the corresponding inset property is not auto, and the corresponding border edge of the component would be outside the corresponding edge of the sticky view rectangle, then the component must be visually shifted (as for relative positioning) to be inward of that sticky view rectangle edge, insofar as it can while its position component remains contained within its containing block. If offsetting the sticky component would put it outside the bounds of its parent the offset is reduced to keep the sticky component within its parents bounds.

A sticky positioned element with a non-auto top value and an auto bottom value will only ever be pushed down by sticky positioning; it will never be offset upwards. In the same way a sticky component with a non-auto left, right or bottom property and a corresponding auto right, left or top property will only ever be pushed right, left or upwards respectively.

Multiple sticky positioned components in the same container are offset independently, and therefore might overlap.

When the value of the top or bottom properties is a percentage, it is a percentage of the nearest vertical scrollable ancestor or the nearest horizontal ancestor for the right or left properties.

Containers with position: sticky are drawn after any non-sticky siblings.

The following example shows a component that stays 10 units down from the top edge of the vertical scrollable. It won’t stick to any other edges because the corresponding right, bottom, or left properties haven’t been set:

{
    "position": "sticky",
    "top": 10
}

The following example defines a component that sticks to both the left and right side of the nearest horizontal scrollable ancestor. If this component reaches the left edge of the scrollable ancestor it sticks 10 units to the right of the left edge of the scrollable. As a result, the left 10 units of the component are hidden from the view. If the scrollable ancestor is scrolled left this component stays at least 20 units from the right edge of the scrollable:

{
    "position": "sticky",
    "left": -10,
    "right": 20
}

Note that the default bounds of the parent of a sticky component can be used to restrict the offsets of a sticky component.

The images below show two components (in red) with parents (in blue) inside a scrollable. The two components have position set to sticky and left set to values of 0px and 20px respectively.

1. Beginning to scroll to the left
1. Beginning to scroll to the left
2. The red '0' element remains in view
2. The red '0' element remains in view
3. When the red '0' element reaches the edge of its direct parent, it begins to move out of view
3. When the red '0' element reaches the edge of its direct parent, it begins to move out of view
4. The blue '1' element stays in view with an offset of 20px from the left edge of the scrollable
4. The blue '1' element stays in view with an offset of 20px from the left edge of the scrollable
{
    "type": "APL",
    "version": "1.8",
    "mainTemplate": {
        "item": [
            {
                "type": "ScrollView",
                "width": 500,
                "height": 500,
                "item": {
                    "type": "Container",
                    "height": 1000,
                    "width": 500,
                    "items": [
                        {
                            "type": "Frame",
                            "height": 300,
                            "width": 500,
                            "backgroundColor": "#1a73e8",
                            "items": [
                                {
                                    "type": "Container",
                                    "height": 300,
                                    "width": 500,
                                    "items": [
                                        {
                                            "position": "sticky",
                                            "top": 0,
                                            "type": "Frame",
                                            "height": 100,
                                            "width": 500,
                                            "backgroundColor": "#dc3912",
                                            "items": []
                                        }
                                    ]
                                }
                            ]
                        },
                        {
                            "type": "Frame",
                            "height": 100,
                            "width": 500,
                            "backgroundColor": "white"
                        },
                        {
                            "type": "Frame",
                            "height": 1000,
                            "width": 500,
                            "backgroundColor": "#1a73e8",
                            "items": [
                                {
                                    "type": "Container",
                                    "height": 300,
                                    "width": 500,
                                    "items": [
                                        {
                                            "position": "sticky",
                                            "top": 20,
                                            "type": "Frame",
                                            "height": 100,
                                            "width": 500,
                                            "backgroundColor": "#dc3912",
                                            "items": []
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            }
        ]
    }
}

start, end

When specified, the start and end properties override left and right for specifying the component position. The override depends on the layoutDirection property:

Property Left-to-right ("LTR") Right-to-left ("RTL")

start

Overrides left

Overrides right

end

Overrides right

Overrides left

The following example shows a component with absolute positioning. When the layoutDirection for the Container is RTL, this component displays 5 units from the top-right of its parent container. The start property (5) overrides the right property (10).

{
    "position": "absolute",
    "width": 100,
    "height": 100,
    "start": 5,
    "left": 10,
    "right": 10,
    "top": 5
}

grow, shrink

Flexbox grow and shrink properties. A positive grow value stretches the component proportionally when there is extra space in the container. A positive shrink value allows the component to shrink below its normal size when there is not enough space in the container.

Negative grow or shrink values are ignored.

numbering

Controls the ordinal value when the parent has set numbered. This property controls how the ordinal value updates for the next child in the sequence, not the current child in the sequence.

  • normal: The next child's ordinal = ordinal + 1.
  • skip: The next child's ordinal = ordinal
  • reset: The next child's ordinal = 1

spacing

An amount of spacing to add between this component and the previous child component in the layout. The first item in the layout ignores spacing. Specify the spacing in absolute dimensions. The spacing property doesn't support relative dimensions.

The spacing properties applies to child components where position is relative. The property is ignored for child components where position is absolute.