Layout
This section explains the fundamental rule Komplete UI's layout system uses:
Parent proposes size. Child chooses size. Parent positions child.
Consider the following example component, where a Text
component is layered on top of a Rectangle
using a ZStack
.
component Example {
ZStack {
Rectangle(color: Color(0xFFFF0000))
Text("Text")
}
with { Frame(width: 200, height: 200) }
}
The following image demonstrates the resulting layout:
To understand how this layout is created we can consider the following dialog between the components:
Frame: "Hi ZStack, I propose you 200 pixels of width, and 200 pixels of height."
ZStack: "Hmmm, before I'll let you know my size, I'll ask my children what size they want."
ZStack: "Hey Rectangle, You could be 200 pixels wide, and 200 tall."
Rectangle: "OK, I would like to fill the entire space."
ZStack: "Hey Text, You could be 200 pixels wide, and 200 tall."
Text: "Hey, ZStack I only need enough to display my text."
ZStack: “Fair enough, I'll put you in the center.”
ZStack: "Hey Frame, since Rectangle wants to fill the entire area I’ve decided that my size is also going to be 200 pixels wide, and 200 pixels tall."
Z-Level Stacking of Components
In this section you'll learn three different ways how to stack components on top of each other.
Overlay
The Overlay
modifier allows you to layer components in front of another one. In difference to the ZStack
the size of the background component is unchanged and will be used as suggestion for the overlayed components.
Consider the following example where a Text
is overlayed on top of a Rectangle
bound by 100x100 pixels:
import { Rectangle, Text, Frame, Overlay } from ui
export var main = Rectangle(color: Color(0xFFDFDFDF)) with {
Frame(width: 100, height: 100)
Overlay {
Text("Hello Long Text")
}
}
You can see that the text is wrapped, because it doesn't fit into the suggested area driven by the Frame
. Here's the same example using a ZStack
instead:
import { Rectangle, ZStack, Text, Frame } from ui
export var main = ZStack {
Rectangle(color: Color(0xFF565656)) with { Frame(width: 100, height: 100) }
Text("Hello Long Text", color: Color(0xFFFFFFFF))
}
In the case of the ZStack
the text doesn't have to fit into the Rectangle
. The ZStack
considers all children equally to determine its final size.
Background
The Background
modifier does the opposite of Overlay
and instead layers components behind another one. The size of the foreground component will be suggested to the background components.
Consider the following example where a Rectangle
is put behind some Text
:
import { Rectangle, Background, Text, Frame } from ui
export var main = Text("Hello World", color: Color(0xFFFFFFFF)) with {
Background {
Rectangle(color: Color(0xFF565656))
}
}
You can see that in this case the Text
is the driver of the background size, which is why the Rectangle
fills out the area spanned up by the Text
.
Here's the same example with a ZStack
:
import { Rectangle, ZStack, Text, Frame } from ui
export var main = ZStack {
Rectangle(color: Color(0xFF565656))
Text("Hello World", color: Color(0xFFFFFFFF))
}
In this case, the ZStack
considers all children equally and will fill the entire area of the window, because its child Rectangle
wants to fill everything that's available.