跳到主要内容

列 Column

一个以垂直数组显示其子控件的控件。

要使子控件展开并填充可用的垂直空间,请设置其 expand 属性。

示例

Live example

列间距

import flet as ft

def main(page: ft.Page):
def items(count):
items = []
for i in range(1, count + 1):
items.append(
ft.Container(
content=ft.Text(value=str(i)),
alignment=ft.alignment.center,
width=50,
height=50,
bgcolor=ft.colors.AMBER,
border_radius=ft.border_radius.all(5),
)
)
return items

def spacing_slider_change(e):
col.spacing = int(e.control.value)
col.update()

gap_slider = ft.Slider(
min=0,
max=100,
divisions=10,
value=0,
label="{value}",
width=500,
on_change=spacing_slider_change,
)

col = ft.Column(spacing=0, controls=items(5))

page.add(ft.Column([ ft.Text("Spacing between items"), gap_slider]), col)

ft.app(target=main)

列换行

import flet as ft

HEIGHT = 400

def main(page: ft.Page):
def items(count):
items = []
for i in range(1, count + 1):
items.append(
ft.Container(
content=ft.Text(value=str(i)),
alignment=ft.alignment.center,
width=30,
height=30,
bgcolor=ft.colors.AMBER,
border_radius=ft.border_radius.all(5),
)
)
return items

def slider_change(e):
col.height = float(e.control.value)
col.update()

width_slider = ft.Slider(
min=0,
max=HEIGHT,
divisions=20,
value=HEIGHT,
label="{value}",
width=500,
on_change=slider_change,
)

col = ft.Column(
wrap=True,
spacing=10,
run_spacing=10,
controls=items(10),
height=HEIGHT,
)

page.add(
ft.Column(
[
ft.Text(
"Change the column height to see how child items wrap onto multiple columns:"
),
width_slider,
]
),
ft.Container(content=col, bgcolor=ft.colors.AMBER_100),
)

ft.app(target=main)

列垂直对齐

import flet as ft

def main(page: ft.Page):
def items(count):
items = []
for i in range(1, count + 1):
items.append(
ft.Container(
content=ft.Text(value=str(i)),
alignment=ft.alignment.center,
width=50,
height=50,
bgcolor=ft.colors.AMBER_500,
)
)
return items

def column_with_alignment(align: ft.MainAxisAlignment):
return ft.Column(
[
ft.Text(str(align), size=10),
ft.Container(
content=ft.Column(items(3), alignment=align),
bgcolor=ft.colors.AMBER_100,
height=400,
),
]
)

page.add(
ft.Row(
[
column_with_alignment(ft.MainAxisAlignment.START),
column_with_alignment(ft.MainAxisAlignment.CENTER),
column_with_alignment(ft.MainAxisAlignment.END),
column_with_alignment(ft.MainAxisAlignment.SPACE_BETWEEN),
column_with_alignment(ft.MainAxisAlignment.SPACE_AROUND),
column_with_alignment(ft.MainAxisAlignment.SPACE_EVENLY),
],
spacing=30,
alignment=ft.MainAxisAlignment.START,
)
)

ft.app(target=main)

列水平对齐

import flet as ft

def main(page: ft.Page):
def items(count):
items = []
for i in range(1, count + 1):
items.append(
ft.Container(
content=ft.Text(value=str(i)),
alignment=ft.alignment.center,
width=50,
height=50,
bgcolor=ft.colors.AMBER_500,
)
)
return items

def column_with_horiz_alignment(align: ft.CrossAxisAlignment):
return ft.Column(
[
ft.Text(str(align), size=16),
ft.Container(
content=ft.Column(
items(3),
alignment=ft.MainAxisAlignment.START,
horizontal_alignment=align,
),
bgcolor=ft.colors.AMBER_100,
width=100,
),
]
)

page.add(
ft.Row(
[
column_with_horiz_alignment(ft.CrossAxisAlignment.START),
column_with_horiz_alignment(ft.CrossAxisAlignment.CENTER),
column_with_horiz_alignment(ft.CrossAxisAlignment.END),
],
spacing=30,
alignment=ft.MainAxisAlignment.START,
)
)

ft.app(target=main)

无限滚动列表

以下示例演示了在用户滚动到底部时动态添加列表项,从而营造无限列表的错觉:

import threading
import flet as ft

class State:
i = 0

s = State()
sem = threading.Semaphore()

def main(page: ft.Page):
def on_scroll(e: ft.OnScrollEvent):
if e.pixels >= e.max_scroll_extent - 100:
if sem.acquire(blocking=False):
try:
for i in range(0, 10):
cl.controls.append(ft.Text(f"Text line {s.i}", key=str(s.i)))
s.i += 1
cl.update()
finally:
sem.release()

cl = ft.Column(
spacing=10,
height=200,
width=200,
scroll=ft.ScrollMode.ALWAYS,
on_scroll_interval=0,
on_scroll=on_scroll,
)
for i in range(0, 50):
cl.controls.append(ft.Text(f"Text line {s.i}", key=str(s.i)))
s.i += 1

page.add(ft.Container(cl, border=ft.border.all(1)))

ft.app(main)

将列进行编程式滚动

以下示例演示了各种 scroll_to() 选项,并定义了一个自定义的滚动条主题:

import flet as ft

def main(page: ft.Page):
page.theme = ft.Theme(
scrollbar_theme=ft.ScrollbarTheme(
track_color={
ft.MaterialState.HOVERED: ft.colors.AMBER,
ft.MaterialState.DEFAULT: ft.colors.TRANSPARENT,
},
track_visibility=True,
track_border_color=ft.colors.BLUE,
thumb_visibility=True,
thumb_color={
ft.MaterialState.HOVERED: ft.colors.RED,
ft.MaterialState.DEFAULT: ft.colors.GREY_300,
},
thickness=30,
radius=15,
main_axis_margin=5,
cross_axis_margin=10,
# interactive=False,
)
)

cl = ft.Column(
spacing=10,
height=200,
width=float("inf"),
scroll=ft.ScrollMode.ALWAYS,
)
for i in range(0, 100):
cl.controls.append(ft.Text(f"Text line {i}", key=str(i)))

def scroll_to_offset(e):
cl.scroll_to(offset=100, duration=1000)

def scroll_to_start(e):
cl.scroll_to(offset=0, duration=1000)

def scroll_to_end(e):
cl.scroll_to(offset=-1, duration=2000, curve=ft.AnimationCurve.EASE_IN_OUT)

def scroll_to_key(e):
cl.scroll_to(key="20", duration=1000)

def scroll_to_delta(e):
cl.scroll_to(delta=40, duration=200)

def scroll_to_minus_delta(e):
cl.scroll_to(delta=-40, duration=200)

page.add(
ft.Container(cl, border=ft.border.all(1)),
ft.ElevatedButton("Scroll to offset 100", on_click=scroll_to_offset),
ft.Row(
[
ft.ElevatedButton("Scroll to start", on_click=scroll_to_start),
ft.ElevatedButton("Scroll to end", on_click=scroll_to_end),
]
),
ft.ElevatedButton("Scroll to key '20'", on_click=scroll_to_key),
ft.Row(
[
ft.ElevatedButton("Scroll -40", on_click=scroll_to_minus_delta),
ft.ElevatedButton("Scroll +40", on_click=scroll_to_delta),
]
),
)

ft.app(main)

属性

alignment

子控件在垂直方向上的对齐方式。

属性值为 MainAxisAlignment 枚举值,有以下选项:

  • START(默认)
  • END
  • CENTER
  • SPACE_BETWEEN
  • SPACE_AROUND
  • SPACE_EVENLY

auto_scroll

当子控件更新时,如果要自动移动滚动条位置到末尾,则为 True。如果需要使用 scroll_to() 方法,则必须为 False

controls

要在 Column 中显示的控件列表。

horizontal_alignment

子控件在水平方向上的对齐方式。

属性值为 CrossAxisAlignment 枚举值,有以下选项:

  • START(默认)
  • CENTER
  • END
  • STRETCH
  • BASELINE

on_scroll_interval

on_scroll 事件的节流间隔,以毫秒为单位。默认为 10

scroll

启用垂直滚动以防止列中的内容溢出。

属性值是可选的ScrollMode枚举,默认为None

支持的值:

  • None(默认)- 列不可滚动,其内容可能会溢出。
  • AUTO - 启用滚动,并且仅在发生滚动时显示滚动条。
  • ADAPTIVE - 启用滚动,并且始终在Web或桌面应用程序上显示滚动条。
  • ALWAYS - 启用滚动,并始终显示滚动条。
  • HIDDEN - 启用滚动,但始终隐藏滚动条。

spacing

列中控件之间的间距。默认值为10个虚拟像素。只有在alignment设置为startendcenter时才应用间距。

run_spacing

wrap=True时,在运行中将子控件放入额外的列(行)中。默认值为10。

tight

指定垂直方向上应占用多少空间。默认值为False - 将所有空间分配给子控件。

wrap

当设置为True时,如果子控件不适合单列,则将其放入其他列(行)中。

方法

scroll_to(offset, delta, key, duration, curve)

将滚动位置移动到绝对offset、相对delta或跳转到具有指定key的控件。

offset是滚动控件最小和最大范围之间的绝对值,例如:

products.scroll_to(offset=100, duration=1000)

offset可以为负数,以从滚动的末尾进行滚动。例如,滚动到最末尾:

products.scroll_to(offset=-1, duration=1000)

delta允许相对于当前位置移动滚动。使用正数delta向前滚动,使用负数delta向后滚动。例如,向前移动50像素的滚动:

products.scroll_to(delta=50)

key允许将滚动位置移动到具有指定key的控件。大多数Flet控件都有key属性,该属性在Flutter中被翻译为“全局键”。key必须在整个页面/视图中是唯一的。例如:

import flet as ft

def main(page: ft.Page):
cl = ft.Column(
spacing=10,
height=200,
width=200,
scroll=ft.ScrollMode.ALWAYS,
)
for i in range(0, 50):
cl.controls.append(ft.Text(f"Text line {i}", key=str(i)))

def scroll_to_key(e):
cl.scroll_to(key="20", duration=1000)

page.add(
ft.Container(cl, border=ft.border.all(1)),
ft.ElevatedButton("Scroll to key '20'", on_click=scroll_to_key),
)

ft.app(main)
备注

scroll_to()方法不适用于动态构建其项目的ListViewGridView控件。

duration是滚动动画持续时间,以毫秒为单位。默认为0-无动画。

curve配置动画曲线。默认为ft.AnimationCurve.EASE

事件

on_scroll

当用户更改滚动位置时触发。

事件处理程序参数是ft.OnScrollEvent类的实例,具有以下属性:

  • event_type(str)- 滚动事件的类型:
    • start- 控件开始滚动;
    • update- 控件已更改其滚动位置;
    • end- 控件停止滚动;
    • user- 用户更改了滚动方向;
    • over- 控件未更改其滚动位置,因为更改会导致其滚动位置超出其滚动范围;
  • pixels(float)- 当前滚动位置,以逻辑像素为单位。
  • min_scroll_extent(float)- pixels的最小值。
  • max_scroll_extent(float)- pixels的最大值。
  • viewport_dimension(float)- 视口的大小。
  • scroll_delta(float)- 滚动控件滚动的距离,以逻辑像素为单位。仅在update事件中设置。
  • direction(str)- 用户滚动的方向:idleforwardreverse。仅在user事件中设置。
  • overscroll(float)- 滚动控件避免滚动的逻辑像素数。仅在over事件中设置。
  • velocity(float)- 当发生此超滚动时,ScrollPosition正在更改的速度。仅在over事件中设置。

扩展子控件

当将子控件放入列中时,您可以将其"展开"以填充可用空间。每个控件都有一个expand属性,可以是布尔值(True-将控件展开以填充所有可用空间)或整数-一个"展开因子",指定如何将空闲空间与其他展开的子控件进行划分。例如,以下代码创建了一个列,其中一个容器占据所有可用空间,底部的文本控件用作状态栏:

r = ft.Column([
ft.Container(expand=True, content=ft.Text("Here is search results")),
ft.Text("Records found: 10")
])

以下具有数字展开因子的示例创建了一个列,其中包含3个容器,并且它们的高度分别为20%(1/5)60%(3/5)20%(1/5)

r = ft.Column([
ft.Container(expand=1, content=ft.Text("Header")),
ft.Container(expand=3, content=ft.Text("Body")),
ft.Container(expand=1, content=ft.Text("Footer"))
])

通常,子控件的结果高度以百分比计算为expand / sum(all expands) * 100%