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

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

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

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

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

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

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: Optional[Alignment] = None

Alignment of the control within its parent.

animate_alignclass-attributeinstance-attribute

animate_align: Optional[AnimationValue] = None

Enables implicit animation of the align property.

More information here.

animate_marginclass-attributeinstance-attribute

animate_margin: Optional[AnimationValue] = None

Enables implicit animation of the margin property.

More information here.

animate_offsetclass-attributeinstance-attribute

animate_offset: Optional[AnimationValue] = None

Enables implicit animation of the offset property.

More information here.

animate_opacityclass-attributeinstance-attribute

animate_opacity: Optional[AnimationValue] = None

Enables implicit animation of the opacity property.

More information here.

animate_positionclass-attributeinstance-attribute

animate_position: Optional[AnimationValue] = None

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

More information here.

animate_rotationclass-attributeinstance-attribute

animate_rotation: Optional[AnimationValue] = None

Enables implicit animation of the rotate property.

More information here.

animate_scaleclass-attributeinstance-attribute

animate_scale: Optional[AnimationValue] = None

Enables implicit animation of the scale property.

More information here.

animate_sizeclass-attributeinstance-attribute

animate_size: Optional[AnimationValue] = None

TBD

aspect_ratioclass-attributeinstance-attribute

aspect_ratio: Optional[Number] = 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: Optional[Number] = 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, flet.Page.overlay list.

flipclass-attributeinstance-attribute

flip: Optional[Flip] = 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: Optional[Number] = None

Imposed Control height in virtual pixels.

leftclass-attributeinstance-attribute

left: Optional[Number] = 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, flet.Page.overlay list.

marginclass-attributeinstance-attribute

margin: Optional[MarginValue] = None

Sets the margin of the control.

offsetclass-attributeinstance-attribute

offset: Optional[OffsetValue] = 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: Optional[Number] = 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, flet.Page.overlay list.

rotateclass-attributeinstance-attribute

rotate: Optional[RotateValue] = 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: Optional[ScaleValue] = 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: Optional[Number] = 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, flet.Page.overlay list.

transformclass-attributeinstance-attribute

transform: Optional[Transform] = 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: Optional[Number] = None

Imposed Control width in virtual pixels.

Events

on_animation_endclass-attributeinstance-attribute

on_animation_end: Optional[ControlEventHandler[LayoutControl]] = 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: Optional[EventHandler[LayoutSizeChangeEvent[LayoutControl]]] = None

Called when the size of this control changes.

size_change_interval defines how often this event is called.