Skip to main content

LayoutControl

Base class for visual controls that participate in page layout.

LayoutControl extends Control with common visual layout capabilities, including:

Use LayoutControl as the base for custom visual controls rendered on the page surface. For popup controls, use DialogControl; for non-visual integrations, use Service.

Inherits: Control

Properties

Events

Examples

Flip

play_arrowTry Online
import flet as ft


def main(page: ft.Page):
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
page.spacing = 20

def toggle_x(e: ft.Event[ft.Button]):
card.flip.flip_x = not card.flip.flip_x
card.update()

def toggle_y(e: ft.Event[ft.Button]):
card.flip.flip_y = not card.flip.flip_y
card.update()

page.add(
ft.SafeArea(
content=ft.Column(
spacing=20,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
controls=[
card := ft.Container(
width=220,
height=120,
bgcolor=ft.Colors.BLUE_300,
border_radius=16,
alignment=ft.Alignment.CENTER,
content=ft.Text("Flip me", size=24, weight=ft.FontWeight.BOLD),
flip=ft.Flip(
flip_x=False,
flip_y=False,
filter_quality=ft.FilterQuality.MEDIUM,
),
),
ft.Row(
alignment=ft.MainAxisAlignment.CENTER,
controls=[
ft.Button("Toggle X", on_click=toggle_x),
ft.Button("Toggle Y", on_click=toggle_y),
],
),
],
),
)
)


if __name__ == "__main__":
ft.run(main)

Rotate

play_arrowTry Online
from math import pi

import flet as ft


def main(page: ft.Page):
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
page.vertical_alignment = ft.MainAxisAlignment.CENTER
page.add(
ft.SafeArea(
content=ft.Container(
width=220,
height=120,
bgcolor=ft.Colors.BLUE_300,
border_radius=16,
alignment=ft.Alignment.CENTER,
content=ft.Text("Rotate", size=28, weight=ft.FontWeight.BOLD),
rotate=ft.Rotate(
angle=pi / 10,
alignment=ft.Alignment.CENTER,
filter_quality=ft.FilterQuality.MEDIUM,
),
),
)
)


if __name__ == "__main__":
ft.run(main)

RotatedBox

play_arrowTry Online
import flet as ft


def _demo_control(content: ft.Control) -> ft.Container:
return ft.Container(
padding=10,
border=ft.Border.all(1, ft.Colors.OUTLINE_VARIANT),
border_radius=8,
content=content,
)


def _lane(title: str, controls: list[ft.Control]) -> ft.Container:
return ft.Container(
width=540,
padding=12,
border=ft.Border.all(1, ft.Colors.OUTLINE_VARIANT),
border_radius=12,
content=ft.Column(
spacing=8,
controls=[
ft.Text(title, size=16, weight=ft.FontWeight.BOLD),
ft.Divider(height=1),
ft.Row(
spacing=14,
vertical_alignment=ft.CrossAxisAlignment.START,
controls=controls,
),
],
),
)


def main(page: ft.Page):
page.padding = 24
page.scroll = ft.ScrollMode.AUTO
page.add(
ft.SafeArea(
content=ft.Column(
controls=[
ft.Text(
"RotatedBox rotates before layout. Compare occupied "
"space below:",
size=16,
weight=ft.FontWeight.W_500,
),
ft.Column(
spacing=16,
controls=[
_lane(
"Normal controls",
[
_demo_control(ft.Text("Text", size=26)),
_demo_control(
ft.ProgressBar(
width=170, value=0.65, color=ft.Colors.GREEN
)
),
_demo_control(ft.Button("Button")),
],
),
_lane(
"RotatedBox quarter_turns=1",
[
_demo_control(
ft.RotatedBox(
quarter_turns=1,
content=ft.Text("Text", size=26),
)
),
_demo_control(
ft.RotatedBox(
quarter_turns=1,
content=ft.ProgressBar(
width=170,
value=0.65,
color=ft.Colors.GREEN,
),
)
),
_demo_control(
ft.RotatedBox(
quarter_turns=1,
content=ft.Button("Button"),
)
),
],
),
],
),
]
)
)
)


if __name__ == "__main__":
ft.run(main)

Scale

play_arrowTry Online
import flet as ft


def main(page: ft.Page):
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
page.vertical_alignment = ft.MainAxisAlignment.CENTER
page.add(
ft.SafeArea(
content=ft.Container(
width=220,
height=120,
bgcolor=ft.Colors.GREEN_300,
border_radius=16,
alignment=ft.Alignment.CENTER,
content=ft.Text("Scale", size=28, weight=ft.FontWeight.BOLD),
scale=ft.Scale(
scale_x=1.18,
scale_y=0.82,
alignment=ft.Alignment.CENTER,
filter_quality=ft.FilterQuality.MEDIUM,
),
),
)
)


if __name__ == "__main__":
ft.run(main)

Offset

play_arrowTry Online
import flet as ft


def main(page: ft.Page):
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
page.vertical_alignment = ft.MainAxisAlignment.CENTER
page.add(
ft.SafeArea(
content=ft.Stack(
width=460,
height=260,
controls=[
ft.Text(
"Offset translates by control size.",
left=12,
top=8,
size=16,
color=ft.Colors.ON_SURFACE_VARIANT,
),
ft.Container(
left=30,
top=70,
width=170,
height=90,
border_radius=16,
bgcolor=ft.Colors.BLUE_100,
border=ft.Border.all(2, ft.Colors.BLUE_GREY_400),
alignment=ft.Alignment.CENTER,
content=ft.Text(
"Original",
size=20,
color=ft.Colors.BLUE_GREY_700,
),
),
ft.Container(
left=30,
top=70,
width=170,
height=90,
border_radius=16,
bgcolor=ft.Colors.AMBER_300,
alignment=ft.Alignment.CENTER,
content=ft.Text("Offset", size=26, weight=ft.FontWeight.BOLD),
offset=ft.Offset(
x=1.05,
y=0.55,
filter_quality=ft.FilterQuality.MEDIUM,
),
),
ft.Icon(
ft.Icons.ARROW_RIGHT_ALT_ROUNDED,
left=212,
top=82,
size=44,
color=ft.Colors.BLUE_GREY_600,
),
ft.Text(
"offset = Offset(1.05, 0.55)",
left=194,
top=222,
size=14,
color=ft.Colors.ON_SURFACE_VARIANT,
),
],
),
)
)


if __name__ == "__main__":
ft.run(main)

Matrix4 Transform

play_arrowTry Online
from math import pi

import flet as ft


def card(title: str, color: str, matrix: ft.Matrix4) -> ft.Container:
return ft.Container(
width=220,
height=130,
border_radius=18,
bgcolor=color,
padding=12,
content=ft.Text(title, size=18, weight=ft.FontWeight.BOLD),
transform=ft.Transform(
matrix=matrix,
alignment=ft.Alignment.CENTER,
filter_quality=ft.FilterQuality.MEDIUM,
),
)


def main(page: ft.Page):
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
page.scroll = ft.ScrollMode.AUTO
page.spacing = 20

perspective_tilt = (
ft.Matrix4.identity()
.set_entry(3, 2, 0.0018)
.rotate_x(-0.35)
.rotate_y(0.45)
.translate(0, -10, 0)
)

skew_and_rotate = ft.Matrix4.skew_y(0.28).rotate_z(-pi / 14)

mirrored_spin = ft.Matrix4.diagonal3_values(-1, 1, 1).rotate_z(pi / 10)

mix = ft.Matrix4.translation_values(24, -8, 0).multiply(
ft.Matrix4.rotation_z(pi / 16).scale(0.9, 0.9)
)

page.add(
ft.SafeArea(
content=ft.Column(
spacing=20,
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
controls=[
ft.Text("Matrix4 transform recording + replay", size=24),
ft.ResponsiveRow(
controls=[
ft.Container(
col={"sm": 6, "md": 3},
content=card(
"Perspective tilt",
ft.Colors.CYAN_300,
perspective_tilt,
),
),
ft.Container(
col={"sm": 6, "md": 3},
content=card(
"Skew + rotate",
ft.Colors.AMBER_300,
skew_and_rotate,
),
),
ft.Container(
col={"sm": 6, "md": 3},
content=card(
"Mirror + spin",
ft.Colors.PINK_200,
mirrored_spin,
),
),
ft.Container(
col={"sm": 6, "md": 3},
content=card(
"Multiply chain",
ft.Colors.LIGHT_GREEN_300,
mix,
),
),
],
),
],
),
)
)


if __name__ == "__main__":
ft.run(main)

Properties

alignclass-attributeinstance-attribute

align: Alignment | None = None

Alignment of the control within its parent.

animate_alignclass-attributeinstance-attribute

animate_align: AnimationValue | None = None

Enables implicit animation of the LayoutControl.align property.

More information here.

animate_marginclass-attributeinstance-attribute

animate_margin: AnimationValue | None = None

Enables implicit animation of the LayoutControl.margin property.

More information here.

animate_offsetclass-attributeinstance-attribute

animate_offset: AnimationValue | None = None

Enables implicit animation of the LayoutControl.offset property.

More information here.

animate_opacityclass-attributeinstance-attribute

animate_opacity: AnimationValue | None = None

Enables implicit animation of the Control.opacity property.

More information here.

animate_positionclass-attributeinstance-attribute

animate_position: AnimationValue | None = None

Enables implicit animation of the positioning properties (LayoutControl.left, LayoutControl.right, LayoutControl.top and LayoutControl.bottom).

More information here.

animate_rotationclass-attributeinstance-attribute

animate_rotation: AnimationValue | None = None

Enables implicit animation of the LayoutControl.rotate property.

More information here.

animate_scaleclass-attributeinstance-attribute

animate_scale: AnimationValue | None = None

Enables implicit animation of the LayoutControl.scale property.

More information here.

animate_sizeclass-attributeinstance-attribute

animate_size: AnimationValue | None = None

Enables implicit animation of this control's size.

If width or height is set, changes to those dimensions are animated. If neither dimension is set, changes to the control's natural size are animated instead.

More information here.

aspect_ratioclass-attributeinstance-attribute

aspect_ratio: Number | None = None

The aspect ratio of the control. It is defined as the ratio of width to height.

Note

In current implementation, if aspect_ratio is set, width and height on the same control are ignored for final rendered size.

bottomclass-attributeinstance-attribute

bottom: Number | None = None

The distance that the child's bottom edge is inset from the bottom of the stack.

Note

Effective only if this control is a descendant of one of the following: Stack control, Page.overlay list.

flipclass-attributeinstance-attribute

flip: Flip | None = None

Flips this control horizontally and/or vertically.

Set to an instance of Flip to mirror across x-axis, y-axis, or both.

heightclass-attributeinstance-attribute

height: Number | None = None

Imposed Control height in virtual pixels.

leftclass-attributeinstance-attribute

left: Number | None = None

The distance that the child's left edge is inset from the left of the stack.

Note

Effective only if this control is a descendant of one of the following: Stack control, Page.overlay list.

marginclass-attributeinstance-attribute

margin: MarginValue | None = None

Sets the margin of the control.

offsetclass-attributeinstance-attribute

offset: OffsetValue | None = None

Applies a translation transformation before painting the control.

The translation is expressed as an Offset scaled to the control's size. So, Offset(x=0.25, y=0), for example, will result in a horizontal translation of one quarter the width of this control.

Example The following example displays container at 0, 0 top left corner of a stack as transform applies -1 * 100, -1 * 100 (offset * control's size) horizontal and vertical translations to the control:

import flet as ft

def main(page: ft.Page):
page.add(
ft.Stack(
width=1000,
height=1000,
controls=[
ft.Container(
bgcolor=ft.Colors.RED,
width=100,
height=100,
left=100,
top=100,
offset=ft.Offset(-1, -1),
)
],
)
)

ft.run(main)

rightclass-attributeinstance-attribute

right: Number | None = None

The distance that the child's right edge is inset from the right of the stack.

Note

Effective only if this control is a descendant of one of the following: Stack control, Page.overlay list.

rotateclass-attributeinstance-attribute

rotate: RotateValue | None = None

Transforms this control using a rotation around its center.

The value of rotate property could be one of the following types:

  • number - a rotation in clockwise radians. Full circle 360° is math.pi * 2 radians, 90° is pi / 2, 45° is pi / 4, etc.
  • Rotate - allows to specify rotation angle as well as alignment - the location of rotation center.
Example
ft.Image(
src="https://picsum.photos/100/100",
width=100,
height=100,
border_radius=5,
rotate=Rotate(angle=0.25 * pi, alignment=ft.Alignment.CENTER_LEFT)
)

scaleclass-attributeinstance-attribute

scale: ScaleValue | None = None

Scales this control along the 2D plane. Default scale factor is 1.0, meaning no-scale.

Setting this property to 0.5, for example, makes this control twice smaller, while 2.0 makes it twice larger.

Different scale multipliers can be specified for x and y axis, by setting Control.scale property to an instance of Scale class. Either scale or scale_x and scale_y could be specified, but not all of them.

Example
ft.Image(
src="https://picsum.photos/100/100",
width=100,
height=100,
border_radius=5,
scale=ft.Scale(scale_x=2, scale_y=0.5)
)

size_change_intervalclass-attributeinstance-attribute

size_change_interval: int = 10

Sampling interval in milliseconds for on_size_change event.

Setting to 0 calls on_size_change immediately on every change.

topclass-attributeinstance-attribute

top: Number | None = None

The distance that the child's top edge is inset from the top of the stack.

Note

Effective only if this control is a descendant of one of the following: Stack control, Page.overlay list.

transformclass-attributeinstance-attribute

transform: Transform | None = None

Applies a generic matrix transform to this control.

Set to an instance of Transform with a recorded Matrix4 to describe arbitrary transform sequences.

widthclass-attributeinstance-attribute

width: Number | None = None

Imposed Control width in virtual pixels.

Events

on_animation_endclass-attributeinstance-attribute

on_animation_end: (
    ControlEventHandler[LayoutControl] | None
) = None

Called when animation completes.

Can be used to chain multiple animations.

The data property of the event handler argument contains the name of the animation.

More information here.

on_size_changeclass-attributeinstance-attribute

on_size_change: (
    EventHandler[LayoutSizeChangeEvent[LayoutControl]]
    | None
) = None

Called when the size of this control changes.

size_change_interval defines how often this event is called.