Layout Manager
Cross Platform Layout Manager for Android and iOS - April 6th, 2018
Introduction and layout types
The layout manager is responsible for layouting all kind of controls in a precise fashion on a mobile app page. It automatically adopts to the respective screen size and therefore achieves device format independence. The layout manager makes use of layout containers to display the mobile pages.
Currently, there are four major layout containers
- Grid Layout container matrix like layout, great for general purposes
- Vertical Linear Layout stack control vertically
- Horizontal Linear Layout align control next to each other
Some important facts
- The root container is the page. Its of type grid layout and cannot be changed.
- Containers can contain each other
- Create a hierarchy of container to achieve the perfect layout
- XYLayout is not used often, only for special purposes. Pixel perfect layout is best achieved using the Grid, Vertical and Horizontal layout container.
Video Layout
This little video demos how to combine different layout container to achieve complex layouts. Its an overview, not a full training video
General layout properties
There are some shared attributes across all layout containers. You set them by clicking on the container and using the layout panel to specify them:
Margins
The margin settings define the space between the layout container and its content. Increasing the margin moves the content of the container inwards. The values are absolute values in points.
Spacing
The spacing defines the space between controls within a container.
- Grid Layout container supports vertical and horizontal spacing
- Vertical Linear Layout container supports vertical spacing
- Horizontal Linear Layout container supports horizontal spacing
Spacing is not supported for the XY Layout container.
Video demo
We demo the following this this video
- Inserting grid layout container grid1 in page (that is itself a grid)
- Changing background color of grid1
- Setting margins on page grid
- Making child grid grid1 a 4x4 grid by inserting 4 horizontal containers
- Setting spacing
Setting in code
Apart from the editor, you can also set these properties using code. You use properties of the SCDLayoutGridLayout class. For more information on coding layout, see Programmatic UI development
let layout = self.page!.layout as! SCDLayoutGridLayout
layout.marginBottom = 50
layout.marginTop = 50
layout.marginLeft = 30
layout.marginRight = 30
layout.horizontalSpacing = 5
layout.verticalSpacing = 5
Bounding box
A bounding box is a very important concept in order to understand layout behavior. Bounding boxes are used in all kind of graphic tools (Adobe, Sketch...)
A bounding box is a rectangle that encloses the visual control, i.e. container or widget (Horizontal layout container, Label, button ....) and defines the area in which the visual control can be placed.
Basically, a bounding box can have three sizes:
- minimum size, where the size of the bounding box and the visual control are the same
- maximum size, where the size of the bounding box covers as much area as possible and is only constrained by its parent
- custom size, where the width and height is set by the developers
Custom size option is rarely used.
If you choose the maximum size bounding box, the bounding box extends itself in vertical or/and horizontal direction until it reaches the borders of its parent container.
If you choose the minimal size, the bounding box will always be the size of the visual control.
Only when you choose maximum size, can you change the location of the control otherwise, the bounding box is the same size as the control, giving it no place to change/move to.
Fill space - Setting min and max bounding box
You set the behavior of the bounding box, whether it maximizes itself, or minimizes itself, using the two checkboxes on the layout tab. There is one checkbox for each direction
Checked | Unchecked | |
---|---|---|
Horizontal Fill Space | As much space as possible is grabbed / used horizontally | Bounding box has same width as control |
Horizontal Fill Space | As much space as possible is grabbed / used vertically | Bounding box has same height as control |
Video Demo 2
Here a short video to strengthen the understanding of using minimized and maximized bounding box settings:
Bounding box code
let gridData = SCDLayoutGridData()
// Set the to true for maximum bounding box size
// set to false for bounding box to equal control
gridData.isGrabHorizontalSpace = true
gridData.isGrabVerticalSpace = true
// In case of maximum bounding box (isGrabXXXSpace = true)
// we can set the location with the bounding box
gridData.horizontalAlignment = .center
gridData.verticalAlignment = .middle
Width and height constraint
Another important setting to understand is the width and height constraints of the control. Each control has its bounding box that defines the area available to the control. Additional, we can influence the size of the control itself. The width and height constraints define this size.
These can be set to one of two values:
- wrap_content height and / or width of control is equal to the height and width of control content
- match_parent height and / or width of control are equal to size of bounding box
Size constraints in code
let gridData = SCDLayoutGridData()
// set width and height constraints
gridData.heightConstraint = .match_parent
gridData.widthConstraint = .wrap_content
Grid Layout
The Grid Layout arranges the items contained in the layout in a grid like style. Items can be other layout containers or user controls like labels, buttons, list controls… A grid contains of a number of rows and columns. The grid expands dynamically if more items are added. For instance, adding a new label below an existing label in the last row of a grid creates a new row.
The grid layout is the root container of a page and therefore the default layout in which other layout containers are inserted. See this video for a short introduction
Basic Grid Layout behavior
The grid layout consists of rows and columns, therefore forming an n x m matrix of cells.
- Each cell holds exactly one control, for instance label, bitmap.
- To insert more than one control / cell, insert a layout container in the cell that than can contain many controls
- The height of each of row is determined by the tallest control in the row
- The width of each of column is determined by the widest control in the column
Horizontal linear layout
The horizontal linear layout arranges the items within the layout next to each other. It "groups" the items contained in the layout container. You can than specify the alignment of the linear layout itself. This little video illustrates how to
- Insert a horizontal linear layout
- Use the Fill Space check to limit the automatic vertical expansion
- Use the layout options Match Parent vs wrap content so that the layout tighly wraps the the content
- Align left, right and center
Vertical linear layout
The vertical linear layout arranges the items above and below each other. It "groups" the items contained in the layout container. Please see horizontal linear layout for a video demonstration.
XY Layout
The XY Layout allows a pixel perfect placement based on coordinates of items. However, as it doesn't use layout concepts such as alignment and fill space, it doesn't scale automatically to the respective device format.
Working with scroll
To add the ability to scroll horizontally and vertically within a container, you check the scroll flag on the layout panel:
This adds a ScrollableBox to the layout xml. scrollable is set to either horizontal, vertical or all.
That is all that is necessary to use scrolling.
Scroll to position
To scroll to a specific position, let in our case to the middle of the scrollbox, we
0. Add an id to the scrollbox to identify it. We used sg1 here (see prior image)
- get handle on scrollbox using the self.page!.drawing!.find(byId:) method
- Determine total size that the scrollbox encloses using .getContentSize()
- Do simple math to determine scroll position to scroll to
- Scroll to position using .scroll(to:, y:0)
func gotoMiddle() {
// Get scrollbox
let scrollbox = self.page!.drawing!.find(byId:"sg1") as! SCDSvgScrollGroup
// get total size, i.e. the width and height of entire scrollbox
let contentSize = scrollbox.getContentSize()
// the scrollbox.width : visible part of the scrollbox
let position = (contentSize.width - scrollbox.width) / 2
scrollbox.scroll(to: position, y: 0)
}
Makes a nicely scrollable area
Updated about 5 years ago