Skip to content

InputBorder 现在是类层级结构,而非枚举 ​

INFO

本指南以 Flet 1.0.0 为准,内容是最准确的。后续版本可能会新增 API 或增加额外的迁移路径。

破坏性变更与废弃索引列出了为每个版本编写的指南。

概述 ​

Flet 1.0.0 用一套类层级结构替换了 InputBorder 枚举,它与 Flutter 的 InputBorder 相对应:

  • [OutlineInputBorder][flet.OutlineInputBorder] —— 围绕各边的圆角矩形(side、border_radius、gap_padding)
  • [UnderlineInputBorder][flet.UnderlineInputBorder] —— 沿底边的一条线(side、border_radius)
  • [NoInputBorder][flet.NoInputBorder] —— 不绘制任何内容

旧 API 所能表达的一切——以及更多——现在都落在 border 属性上,它接受单个 InputBorder,或是一个将 [ControlState][flet.ControlState] 映射到 InputBorder 的字典。

当新旧写法结合时,新 API 获胜:一个指定了 side 或按状态条目的 border 会完全忽略那些被废弃的属性,而一个裸的 border=ft.InputBorder.UNDERLINE 仍会拾取旧的 border_color。

背景 ​

旧的枚举加五个松散属性无法表达 Flutter 真正的 API:gap_padding 没有被暴露,UnderlineInputBorder 的圆角被忽略,而且错误/禁用边框根本无法设置样式。Flutter 每新增一个边框属性,就需要在顶层控件上再增加一项属性。类层级结构改为随 Flutter 一起扩展:新的边框类型(例如 Flutter 3.44 加入的 ShapedInputBorder)成为新类,而不是每个表单字段上都多几个属性。

迁移指南 ​

边框样式 ​

迁移前代码:

python
ft.TextField(border=ft.InputBorder.OUTLINE)
ft.TextField(border=ft.InputBorder.UNDERLINE)
ft.TextField(border=ft.InputBorder.NONE)

迁移后代码:

python
ft.TextField(border=ft.OutlineInputBorder())  # 默认值;可省略
ft.TextField(border=ft.UnderlineInputBorder())
ft.TextField(border=ft.NoInputBorder())

圆角、颜色与宽度 ​

迁移前代码:

python
ft.TextField(
    border_radius=30,
    border_color=ft.Colors.GREEN_800,
    border_width=2,
)

迁移后代码:

python
ft.TextField(
    border=ft.OutlineInputBorder(
        border_radius=30,
        side=ft.BorderSide(width=2, color=ft.Colors.GREEN_800),
    ),
)

要完全移除边框(之前用 border_width=0 或 border_color=ft.Colors.TRANSPARENT),使用 border=ft.NoInputBorder(),或者 side=ft.BorderSide.none() 来保留轮廓形状以配合填充。

与旧的 border_color 不同,单个边框上显式的 side 只作用于启用状态——聚焦边框仍保持主题色(主色,2px)。若要像旧代码那样也给聚焦边框上色,使用下面按状态的写法。

聚焦(以及其他按状态)边框 ​

迁移前代码:

python
ft.TextField(
    border_radius=30,
    border_color=ft.Colors.GREEN_800,
    focused_border_color=ft.Colors.GREEN_ACCENT_400,
    focused_border_width=5,
)

迁移后代码:

python
ft.TextField(
    border={
        ft.ControlState.DEFAULT: ft.OutlineInputBorder(
            border_radius=30,
            side=ft.BorderSide(color=ft.Colors.GREEN_800),
        ),
        ft.ControlState.FOCUSED: ft.OutlineInputBorder(
            border_radius=30,
            side=ft.BorderSide(width=5, color=ft.Colors.GREEN_ACCENT_400),
        ),
    },
)

支持的 State 键为 DEFAULT、FOCUSED、ERROR 和 DISABLED——错误和禁用边框在以前是无法设置样式的。一个没有显式 side 的状态条目会回退到 DEFAULT 条目的 side,这与旧的 focused_border_color or border_color 的颜色行为一致。

ERROR 条目同时覆盖两种错误状态:字段在失焦时显示错误、以及在聚焦时显示错误。当它没有显式 side 时,聚焦变体会以更粗的 Material 聚焦权重绘制。

注意,显式的 side 会以它指定的精确宽度渲染——ft.BorderSide 默认宽度为 1。旧的隐式聚焦宽度 2(当 focused_border_width 和 border_width 都未设置时应用)不复存在:要在 FOCUSED 条目中保留先前的聚焦强调,请传入 side=ft.BorderSide(width=2, ...)。

DropdownM2.border_radius 以前会同时圆化输入框和打开的菜单。现在它们是分开的:border 塑造输入框,新的 menu_border_radius 塑造菜单。两者都设置才能保持旧外观。

迁移前代码:

python
ft.DropdownM2(border_radius=20)

迁移后代码:

python
ft.DropdownM2(
    border=ft.OutlineInputBorder(border_radius=20),
    menu_border_radius=20,
)

读取与比较边框 ​

ft.InputBorder 不再是枚举,因此那些检查而非设置边框的代码需要更新。没有可供比较或迭代的枚举成员。

迁移前代码:

python
if field.border == ft.InputBorder.NONE:
    ...
for style in ft.InputBorder:
    ...

迁移后代码:

python
if field.border == ft.NoInputBorder():
    ...
for style in (
    ft.OutlineInputBorder(),
    ft.UnderlineInputBorder(),
    ft.NoInputBorder(),
):
    ...

边框按值比较,因此 ft.OutlineInputBorder(border_radius=4) 等于 ft.OutlineInputBorder()——4 是默认值。要只测试边框的种类,使用 isinstance(field.border, ft.OutlineInputBorder)。注意 field.border 也可能保存一个 ControlState 字典,而非单个边框。

需要注意的行为变化 ​

  • 默认采用主题驱动的边框颜色(Material 控件:TextField、Dropdown、DropdownM2)。以前启用状态的边框总是画成黑色,除非设置了 border_color——在深色模式下也一样。现在没有显式 side 的边框会让 Material 主题按状态解析颜色和宽度:聚焦用主色,错误用错误色,启用色来自主题轮廓(或对于 filled 字段,来自其激活指示色)。这是 Flutter 的默认行为,并且在深色模式和自定义主题下都能正确工作。
  • 单个边框上的显式 side 只作用于启用状态。 以前 border_color 也会给聚焦边框上色。现在聚焦、错误和禁用状态都保持主题解析(聚焦:主色,2px),除非你使用 ControlState 字典形式——参见上面的按状态示例来恢复旧的聚焦外观。
  • 下划线边框现在会遵循圆角。 旧的 border_radius 属性只应用于轮廓边框,当 border 为 InputBorder.UNDERLINE 时被静默忽略。UnderlineInputBorder.border_radius 现在会原样传给 Flutter,由它来圆化装饰容器的圆角——在字段为 filled 时可见,因为填充会被裁剪到该圆角。边框本身仍沿底边画成一条线。它的上角默认圆角为 4。
  • CupertinoTextField 绘制的是盒子装饰而非 Material 输入装饰,因此它翻译边框的方式不同。保持 border 未设置会保留原生 iOS 细线,与之前完全一致。两个显式值会改变外观:ft.OutlineInputBorder() 在没有 side 时现在也保留那条原生细线,而 InputBorder.OUTLINE 过去会画一个实心黑色 1px 盒子(传入 side 来自己绘制);并且 ft.NoInputBorder() 现在会真正移除边框,而 InputBorder.NONE 过去是被静默忽略的。带显式 side 的轮廓会在所有边绘制,下划线只绘制底边,现在还会为填充遵循非默认 border_radius。等于轮廓默认值(4)的 border_radius 与未设置无法区分,并保留原生半径 5。在 ControlState 字典形式中,会应用 DEFAULT、FOCUSED 和 DISABLED 条目;ERROR 被忽略,因为该控件不渲染错误状态。

时间线 ​

  • 废弃于:1.0.0
  • 移除于:1.3.0

参考 ​

  • API 文档:[InputBorder][flet.InputBorder]、 [OutlineInputBorder][flet.OutlineInputBorder]、 [UnderlineInputBorder][flet.UnderlineInputBorder]、 [NoInputBorder][flet.NoInputBorder]、 [ControlState][flet.ControlState]
  • Flutter InputBorder API
  • 问题与 PR:#6773
  • 发布说明:Flet 1.0.0

关注我,学习大模型、大数据、Python等热门技术。