Skip to content

SpinKit ​

30 个基于 Flutter 的 flutter_spinkit 包构建的动画加载指示器控件。

用法 ​

把 flet-spinkit 添加到项目依赖中:

uv

bash
uv add flet-spinkit

pip

bash
pip install flet-spinkit  [^1]

[^1]: 之后你需要手动把这个包添加到 requirements.txt 或 pyproject.toml 中。

然后在你的 Flet 应用中导入该包:

python
import flet_spinkit as spins

启动屏 ​

flet-spinkit 还提供了一个名为 spinkit 的启动屏 —— 一个在打包应用启动期间显示的动画加载器。把 flet-spinkit 设为依赖后,在 pyproject.toml 中选择它:

toml
[tool.flet.boot_screen]
name = "spinkit"

[tool.flet.boot_screen.spinkit]
spinner = "WanderingCubes"          # any SpinKit animation (without the "SpinKit" prefix)
spinner_color_light = "#7c4dff"
spinner_color_dark = "#b388ff"
spinner_size = 60
bgcolor_light = "#ffffff"
bgcolor_dark = "#0d0d12"
prepare_message = "Preparing your app…"
startup_message = "Starting up…"

所有选项都是可选的:

选项默认值说明
spinnerWanderingCubes任意 SpinKit 动画,命名时去掉 SpinKit 前缀(例如 Wave、FadingCube、PouringHourGlass)。不区分大小写。
theme_modeautoauto(跟随设备)、light 或 dark。
bgcolor_light / bgcolor_darkFlet theme background背景色。
spinner_color_light / spinner_color_darkFlet theme primary指示器颜色。
spinner_size60指示器的尺寸(逻辑像素)。
text_color_light / text_color_darkFlet theme on-surface消息文本颜色。
prepare_messagenone解包应用期间显示的文本(仅 Android)。
startup_messagenonePython 运行时和应用启动期间显示的文本。
fade_out_duration0应用就绪时的淡出时长(毫秒);0 表示立即移除。

TIP

这个启动屏是 createBootScreen 扩展钩子一个完整、真实的示例 —— 它的源码位于 flet-spinkit 的 src/flutter/flet_spinkit/lib/src/boot_screen.dart 中。

示例 ​

python
import flet_spinkit as spins

import flet as ft

SPINNERS = [
    ("RotatingPlain", spins.RotatingPlain),
    ("DoubleBounce", spins.DoubleBounce),
    ("Wave", spins.Wave),
    ("WanderingCubes", spins.WanderingCubes),
    ("FadingFour", spins.FadingFour),
    ("FadingCube", spins.FadingCube),
    ("Pulse", spins.Pulse),
    ("ChasingDots", spins.ChasingDots),
    ("ThreeBounce", spins.ThreeBounce),
    ("Circle", spins.Circle),
    ("CubeGrid", spins.CubeGrid),
    ("FadingCircle", spins.FadingCircle),
    ("RotatingCircle", spins.RotatingCircle),
    ("FoldingCube", spins.FoldingCube),
    ("PumpingHeart", spins.PumpingHeart),
    ("HourGlass", spins.HourGlass),
    ("PouringHourGlass", spins.PouringHourGlass),
    ("PouringHourGlassRefined", spins.PouringHourGlassRefined),
    ("FadingGrid", spins.FadingGrid),
    ("Ring", spins.Ring),
    ("Ripple", spins.Ripple),
    ("DualRing", spins.DualRing),
    ("SpinningCircle", spins.SpinningCircle),
    ("SpinningLines", spins.SpinningLines),
    ("SquareCircle", spins.SquareCircle),
    ("ThreeInOut", spins.ThreeInOut),
    ("DancingSquare", spins.DancingSquare),
    ("PianoWave", spins.PianoWave),
    ("PulsingGrid", spins.PulsingGrid),
    ("WaveSpinner", spins.WaveSpinner),
]


def main(page: ft.Page):
    page.title = "SpinKit Showcase"
    page.scroll = ft.ScrollMode.AUTO
    page.padding = 20

    color = ft.Colors.BLUE

    page.add(
        ft.GridView(
            runs_count=4,
            max_extent=160,
            child_aspect_ratio=0.9,
            spacing=12,
            run_spacing=12,
            controls=[
                ft.Container(
                    content=ft.Column(
                        [
                            ft.Container(
                                content=cls(color=color, size=50),
                                alignment=ft.Alignment.CENTER,
                                expand=True,
                            ),
                            ft.Text(
                                name,
                                size=11,
                                text_align=ft.TextAlign.CENTER,
                            ),
                        ],
                        horizontal_alignment=ft.CrossAxisAlignment.CENTER,
                        spacing=8,
                    ),
                    bgcolor=ft.Colors.SURFACE_CONTAINER_HIGHEST,
                    border_radius=12,
                    padding=12,
                )
                for name, cls in SPINNERS
            ],
        )
    )


if __name__ == "__main__":
    ft.run(main)
python
import flet_spinkit as spins

import flet as ft


def section(title: str, controls: list) -> ft.Column:
    return ft.Column(
        [
            ft.Text(title, size=14, weight=ft.FontWeight.BOLD),
            ft.Row(controls, spacing=24, wrap=True),
        ],
        spacing=12,
    )


def labeled(spinner, label: str) -> ft.Column:
    return ft.Column(
        [
            ft.Container(
                content=spinner,
                alignment=ft.Alignment.CENTER,
                width=80,
                height=80,
            ),
            ft.Text(
                label,
                size=10,
                text_align=ft.TextAlign.CENTER,
            ),
        ],
        horizontal_alignment=ft.CrossAxisAlignment.CENTER,
        spacing=4,
    )


def main(page: ft.Page):
    page.title = "SpinKit Properties"
    page.scroll = ft.ScrollMode.AUTO
    page.padding = 24

    page.add(
        ft.Text("SpinKit Properties", size=24, weight=ft.FontWeight.BOLD),
        ft.Divider(height=16, color=ft.Colors.TRANSPARENT),
        # Colors
        section(
            "color",
            [
                labeled(spins.RotatingCircle(color=ft.Colors.BLUE, size=50), "BLUE"),
                labeled(spins.RotatingCircle(color=ft.Colors.RED, size=50), "RED"),
                labeled(spins.RotatingCircle(color=ft.Colors.GREEN, size=50), "GREEN"),
                labeled(
                    spins.RotatingCircle(color=ft.Colors.ORANGE, size=50), "ORANGE"
                ),
                labeled(
                    spins.RotatingCircle(color=ft.Colors.PURPLE, size=50), "PURPLE"
                ),
                labeled(spins.RotatingCircle(color=ft.Colors.TEAL, size=50), "TEAL"),
            ],
        ),
        ft.Divider(height=8),
        # Sizes
        section(
            "size",
            [
                labeled(spins.ThreeBounce(color=ft.Colors.BLUE, size=20), "20"),
                labeled(spins.ThreeBounce(color=ft.Colors.BLUE, size=30), "30"),
                labeled(spins.ThreeBounce(color=ft.Colors.BLUE, size=40), "40"),
                labeled(spins.ThreeBounce(color=ft.Colors.BLUE, size=50), "50"),
                labeled(spins.ThreeBounce(color=ft.Colors.BLUE, size=70), "70"),
            ],
        ),
        ft.Divider(height=8),
        # Durations
        section(
            "duration",
            [
                labeled(
                    spins.Pulse(
                        color=ft.Colors.BLUE,
                        size=50,
                        duration=ft.Duration(milliseconds=400),
                    ),
                    "400ms",
                ),
                labeled(
                    spins.Pulse(
                        color=ft.Colors.BLUE,
                        size=50,
                        duration=ft.Duration(milliseconds=700),
                    ),
                    "700ms",
                ),
                labeled(
                    spins.Pulse(
                        color=ft.Colors.BLUE,
                        size=50,
                        duration=ft.Duration(milliseconds=1000),
                    ),
                    "1000ms",
                ),
                labeled(
                    spins.Pulse(
                        color=ft.Colors.BLUE,
                        size=50,
                        duration=ft.Duration(milliseconds=2000),
                    ),
                    "2000ms",
                ),
                labeled(
                    spins.Pulse(
                        color=ft.Colors.BLUE,
                        size=50,
                        duration=ft.Duration(milliseconds=4000),
                    ),
                    "4000ms",
                ),
            ],
        ),
        ft.Divider(height=8),
        # Wave — wave_type
        section(
            "Wave · wave_type",
            [
                labeled(
                    spins.Wave(
                        color=ft.Colors.BLUE, size=50, wave_type=spins.WaveType.START
                    ),
                    "START",
                ),
                labeled(
                    spins.Wave(
                        color=ft.Colors.BLUE, size=50, wave_type=spins.WaveType.CENTER
                    ),
                    "CENTER",
                ),
                labeled(
                    spins.Wave(
                        color=ft.Colors.BLUE, size=50, wave_type=spins.WaveType.END
                    ),
                    "END",
                ),
            ],
        ),
        ft.Divider(height=8),
        # Wave — item_count
        section(
            "Wave · item_count",
            [
                labeled(spins.Wave(color=ft.Colors.BLUE, size=50, item_count=3), "3"),
                labeled(spins.Wave(color=ft.Colors.BLUE, size=50, item_count=5), "5"),
                labeled(spins.Wave(color=ft.Colors.BLUE, size=50, item_count=7), "7"),
                labeled(spins.Wave(color=ft.Colors.BLUE, size=50, item_count=10), "10"),
            ],
        ),
        ft.Divider(height=8),
        # Ring — line_width
        section(
            "Ring · line_width",
            [
                labeled(spins.Ring(color=ft.Colors.BLUE, size=50, line_width=2), "2"),
                labeled(spins.Ring(color=ft.Colors.BLUE, size=50, line_width=5), "5"),
                labeled(spins.Ring(color=ft.Colors.BLUE, size=50, line_width=8), "8"),
                labeled(spins.Ring(color=ft.Colors.BLUE, size=50, line_width=12), "12"),
            ],
        ),
        ft.Divider(height=8),
        # DualRing — line_width
        section(
            "DualRing · line_width",
            [
                labeled(
                    spins.DualRing(color=ft.Colors.BLUE, size=50, line_width=2), "2"
                ),
                labeled(
                    spins.DualRing(color=ft.Colors.BLUE, size=50, line_width=5), "5"
                ),
                labeled(
                    spins.DualRing(color=ft.Colors.BLUE, size=50, line_width=8), "8"
                ),
                labeled(
                    spins.DualRing(color=ft.Colors.BLUE, size=50, line_width=12), "12"
                ),
            ],
        ),
        ft.Divider(height=8),
        # Ripple — border_width
        section(
            "Ripple · border_width",
            [
                labeled(
                    spins.Ripple(color=ft.Colors.BLUE, size=50, border_width=2), "2"
                ),
                labeled(
                    spins.Ripple(color=ft.Colors.BLUE, size=50, border_width=4), "4"
                ),
                labeled(
                    spins.Ripple(color=ft.Colors.BLUE, size=50, border_width=8), "8"
                ),
                labeled(
                    spins.Ripple(color=ft.Colors.BLUE, size=50, border_width=14), "14"
                ),
            ],
        ),
        ft.Divider(height=8),
        # SpinningLines — line_width
        section(
            "SpinningLines · line_width",
            [
                labeled(
                    spins.SpinningLines(color=ft.Colors.BLUE, size=50, line_width=1),
                    "1",
                ),
                labeled(
                    spins.SpinningLines(color=ft.Colors.BLUE, size=50, line_width=2),
                    "2",
                ),
                labeled(
                    spins.SpinningLines(color=ft.Colors.BLUE, size=50, line_width=4),
                    "4",
                ),
                labeled(
                    spins.SpinningLines(color=ft.Colors.BLUE, size=50, line_width=6),
                    "6",
                ),
            ],
        ),
        ft.Divider(height=8),
        # PianoWave — item_count
        section(
            "PianoWave · item_count",
            [
                labeled(
                    spins.PianoWave(color=ft.Colors.BLUE, size=50, item_count=3), "3"
                ),
                labeled(
                    spins.PianoWave(color=ft.Colors.BLUE, size=50, item_count=5), "5"
                ),
                labeled(
                    spins.PianoWave(color=ft.Colors.BLUE, size=50, item_count=8), "8"
                ),
                labeled(
                    spins.PianoWave(color=ft.Colors.BLUE, size=50, item_count=12), "12"
                ),
            ],
        ),
    )


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

可用的控件 ​


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