Skip to main content

Layout

Understanding layouting is one of the first steps one needs to undertake, to create beautiful and functional mobile applications with mos. Using our predefined layers as building blocks, attaching them to one another and customizing them to your liking are just some of the concepts you need to learn to get the most out of our technology and to be able to build your application to match your design and your vision.

Basic structure

Layouts consist of one or more layers, that together define the look of, for example, a button, an interactive tile, a complex element or the whole screen. A name field on top defines the the layout itself and should ideally match the name of the file so that it can be easily recognized. The layers are listed as a list (an array) of layers from top to bottom.

basic structure
{
"name": "myLayout",
"layers": [
{
"type": "color",
...
},
{
"type": "text",
...
}
]
}

visualization of layer stacking

note

mos. honors the order of the listed elements: The layers towards the end of the list will be higher on the layer stack compared to layers at the beginning of the list, which will be lower on the stack. This concept can be used to order layers on the z-axis and therefore overlay layers with one another, i.e. the text on a button.

Basic attributes

Every layer needs an attribute named type. As the name suggests, it defines what kind of layer will be specified. Besides that, from the simplest color-layer to a complex chat-layer, all layers share a common set of attribues, that are available to every layer regardless of the actual type. These attributes can be used for a variety of things, from customization to structuring. While none of these attributes are actually required, depending on what you are trying to accomplish and how readable you want your layout to be, some attributes may be recommended.

KeyTypeDescriptionDefault Value
"actions"ActionListList of actions, which will be executed when the layer is tapped.null
"borderColor"ColorThe color of the border in hex color value.null
"borderRadius"UnitSizeThe radius applies to all corners; with a borderWidth of 0 the border is not drawn and radius is set anyway.0
"borderWidth"UnitSizeThe width of the border.0
"bottomLeftRadius"UnitSizeRadius for the bottom left corner.0
"bottomRightRadius"UnitSizeRadius for the bottom right corner.0
"classes"Array[String]List of classes for layer styles.null
"conditions"ConditionsList of conditions to alter the layer state.null
"constraints"ConstraintsA list of constraints defining the position of the layer in a layout.null
"consumesKeyboard"BooleanThis layer will be used to shrink, if a keyboard is shown.null
"dataKey"StringName for assigning data to this layer.null
"hidden"BooleanIndicates whether the layer is hidden. Default: false.false
"layerRotation"NumberThe layer is rotated by the specified degree.0
"name"StringUnique name in the layout. Used for alignment or actions.null
"opacity"NumberThe opacity of the layer.1
"overInsetBottom"BooleanDetermines if this layer ignores the save space at the bottom of the device.false
"overInsetTop"BooleanDetermines if this layer ignores the save space at the top of the device.false
"safeArea"SafeAreaTypeObjectundefinednull
"shadowElevation"NumberThe elevation of this layer for casting shadows.0
"state"StringThe state the layer will use as default."default"
"states"LayerStatesA list of named states that affect the appearance of the layer.null
"topLeftRadius"UnitSizeRadius for the top left corner.0
"topRightRadius"UnitSizeRadius for the top right corner.0
"touchFeedback"TouchFeedbackDetermines if the layer should show a touch feedback if touched."visible"
"trackingKey"StringDefines a key for a scroll event.null
"value"Value(Initial) value of the layer.null

Layouting basics

Every layer within mos. is considered a rectangle, and positioning and sizing of a layer can be achieved by multiple means. There are two concepts of positioning this rectangle - dynamic positions based on grids or absolute/relative layouts with anchors, which we will both detail below.

Anchor basics

Layouts often consist of multiple layers with absolut or relative positioning - in both cases you will need anchors. These anchors can define the origin position of the layer, as well as a the size of the layer relative to the screen size or another layer.

Think of layouting anchors as a compass: There are the main four cardinal points, i.e. n (north), e (east), s (south) and w (west), as well as c, the center point of a layer. Note that in mos., these values should be considered as flanks and not a singular point (see advanced sizing) as well. There are also points right between the main cardinal points, like ne (north-east), se (south-east), sw (south-west) and nw (north-west).

note

Since layouting in mos. always starts at the top left corner, the achor nw is the default value and therefore does not technically need to be set.

visualization of anchors in mos. visualization of anchors in mos.

Anchoring

When defining a layer's constraints, you can use anchors to attach one point of your layer to another point of a relative layer.

note

Keep in mind that n, e, s and w anchors are considered flanks and not determined points. If you attach, for example, the anchor w to the anchor e of another layer, it is not determined where the layer are attached to each other - theoretically both layers could slide up or down this shared axis.

Layouting constraints

The size and position of a layer is definded by constraints. There are multiple types of constraints, each with unique properties and therefore use cases. Knowing which one to use is a key aspect of layouting a layer to achieve a fully functional layout, especially for different devices, resolutions and screen sizes.
Constraints can be specified as pt, dp, % or px, see UnitSize for more information.

pos constraint

When you define the constraints for a layer with absolute or relative positioning, this constraint is used to position the layer absolutely in relation to the screen/the current view or relative to another layer.

The position constraint's attributes are:

AttributeDescriptionDefault Value
"x"The position as a horizontal translation to its reference point. Positive values indicate a translation to the right, negative values to the left.null
"y"The position as a vertical translation to its reference point. Positive values indicate a translation downwards, negative values upwards.null
"anchor"The origin point of the rectangular layer itself and for pos constraint values to be applied to.nw
"relativeAnchor"The attachment point of another rectangular layer for this layer to be relative to. If not set, defaults to top-left point of screen or surrounding layer.nw
"relativeTo"The name of the layer this layer should be positioned relative to.null
pos constraint
{
"type": "pos",
"x": "12pt",
"y": "6pt",
"anchor": "sw",
"relativeAnchor": "ne",
"relativeTo": "myLayer"
}

size constraint

The size constraint enables you to set the dimensions for the rectangular layer.

The size constraint's attributes are:

AttributeDescriptionDefault Value
"width"The width of the layer in dp, pt or %.null
"height"The height of the layer in dp, pt or %.null
"relativeTo"The name of the layer the current layer should be sized relative to.null
size constraint
{
"type": "size",
"height": "240pt",
"width": "144pt"
}

grid constraint

If you define the constraints for a layer that is displayed within a grid, you can set how many columns the element will occupy within the grid (horizontal expansion) and how tall it will be, depending on either its attribute height or its aspectRatio (vertical expansion). This special constraint is only valid as a constraint type for layers within a grid.

The grid constraint's attributes are:

AttributeDescriptionDefault Value
"colSpan"The number of columns the layer should occupy within the grid.null
"aspectRatio"The height of the layer in relation to its width (colSpan).null
"height"The height of the layer in dp, pt or %.null
grid constraint
{
"type": "grid",
"colSpan": "4",
"aspectRatio": "2"
}
note

Only one attribute defining the vertical size (height, aspectRatio) should be present at any time.

aspect constraint

This special constraint can be used to define the size of a layer based on its aspect ratio in relation to a size set by another constraint.

AttributeDescriptionDefault Value
"ratio"The height of the layer in relation to its width.null
aspect constraint
{
"type": "aspect",
"ratio": "1.25"
}
note

The ratio value of 1 can be considered as a 1:1 ratio, which will result in a square.
The special ratio value of content can only be applied to image layers to keep the original aspect ratio of the image.
This constraint is only applicable to certain layers, i.e. image-layer.

Advanced sizing

Dynamic content sizing

In some cases, defining the size of a layer as a fixed value results in the content being cut off or gaps between the layers dimensions and its actual content, due to varying aspect ratios or dynamic content lengths. To combat this issue, text and container layers can be configured to be of dynamic size, depending on their content. Take a closer look at the following example:

dynamic sizing by defining the flank of a text layer
{
"name": "myText",
"type": "text",
"value": "This text will differ in length depending on the response of something outside the app.",
"constraints": [
{
"type": "pos",
"x": "0pt",
"y": "0pt"
},
{
"type": "pos",
"anchor": "e",
"relativeAnchor": "e",
"x": "0pt"
}
]
}

By defining the top-left anchor and the flank on the right, the layer has an origin point and is limited in its horizontal expansion by the defined flank east (e). If the content size is greater than the available space in the horizontal dimension, the text will break at the end of the line and continue on the next as many times as it needs to do until all content is displayed (provided the lineBreakMode is set accordingly, see text).

anchor spanning / corner pinning

Another way of defining the size of a layer uses two opposite corners of the rectangle to pin and therefore setting its size limits in all dimensions (see example 3 below).

Examples

A few examples on layouting multiple layers in various ways.

  1. This first example shows you how to attach two layers to one another, in this case positioning the text at the center of a button.
using relative positioning to another layer
{
"name": "button",
"type": "color",
"constraints": [
{
"type": "pos",
"x": "0",
"y": "0"
},
{
"type": "size",
"height": "40pt",
"width": "120pt"
}
]
},
{
"name": "buttonText",
"type": "text",
"value": "Click me!",
"constraints": [
{
"type": "pos",
"anchor": "c",
"relativeAnchor": "c",
"relativeTo": "button",
"x": "0pt",
"y": "0pt"
},
{
"type": "size",
"height": "40pt",
"width": "120pt"
}
]
}
  1. This example shows how a grid constraint can be used. It defines that the color layer will occupy 6 of 12 available columns of the grid and a height of 240pt.
using grid constraints
{
"name": "myGrid",
"type": "grid",
"columns": "12",
"constraints": [
{
"type": "pos",
"x": "0pt",
"y": "0pt"
},
{
"type": "size",
"height": "100%",
"width": "100%"
}
],
"children": [
{
"name": "colorArea",
"type": "color",
"value": "#ff0000",
"constraints": [
{
"type": "grid",
"colSpan": "6",
"height": "240pt"
}
]
}
]
}
  1. This example will demonstrate an advanced technique of defining the size of an layer by pinning its nw anchor at the top left of the screen and using its se anchor on the opposite side to pin it over the entire available area.
pinning two opposite corners of a layer to define size
{
"name": "colorArea",
"type": "color",
"value": "#ff0000",
"constraints": [
{
"type": "pos",
"x": "0pt",
"y": "0pt"
},
{
"type": "size",
"anchor": "se",
"relativeAnchor": "se",
"x": "0pt",
"y": "0pt"
}
]
}