Flutter iOS 启动屏幕与应用图标 是做什么的?
针对 Flutter 应用的经过实战检验的模式:在第一帧显示原生启动 Logo,以及遵循 iOS 自定义 → 默认 / 深色 / 清除 / 着色的主屏幕图标。
何时使用
- 冷启动时在 Flutter 加载前显示空白白色/象牙白屏幕
- 需要随系统外观变化(而非应用内 ThemeCubit 控制)的浅色 + 深色启动 Logo
- 需要 iOS 18+ 深色 / 着色 / 透明应用图标变体
何时避免使用
- 仅涉及 Android 启动屏幕 / Flutter 应用内 SplashScreen
- 通过更改应用内主题切换(HydratedBloc)来控制外观——这不影响 LaunchScreen 或 SpringBoard 图标
关键规则(不可跳过)
- 启动 Logo 必须作为松散 PNG 文件放置在应用包中,而不是 Asset Catalog 中的 imageset。SplashBoard 经常在第一次快照时从 Assets.car 加载
UIImage imageNamed失败 → 导致 2-3 秒的空白画布。 - 如果相同的基本名称已存在为松散文件,则请勿将 BrandLogo 放入 Assets.xcassets——目录会胜出,导致加载失败。
- LaunchScreen 上的背景颜色必须在故事板中显式指定为 sRGB。命名颜色(例如
LaunchBackground)通常无法在启动快照中切换。 - 特征变化键是
userInterfaceStyle=dark(不是interfaceStyle,也不是luminosity=dark)。 - 切勿通过将独立的
ibtoolstoryboardc 复制到已构建的.app中来验证启动——这会导致黑色闪烁。始终使用flutter build ios --simulator(或真机),然后卸载 + 重新安装。 - 在添加深色/着色图标后,不要运行
flutter_launcher_icons——它会覆盖Contents.json并删除外观配置。 - 主屏幕图标遵循 iPhone 外观 / 自定义设置,而不是 Flutter 主题。透明图标是从着色图标派生而来;没有单独的透明图标槽位。
工作流清单
Progress:
- [ ] 1. 生成浅色 + 深色启动 PNG(@1x/@2x/@3x)
- [ ] 2. 复制到 ios/Runner/ 并添加到 Copy Bundle Resources(pbxproj)
- [ ] 3. 从 Assets.xcassets 中删除任何 BrandLogo*.imageset
- [ ] 4. 更新 LaunchScreen.storyboard(松散图像名称 + 显式颜色)
- [ ] 5. 可选:为 Main.storyboard / SceneDelegate 过渡创建 LaunchBackground.colorset
- [ ] 6. 生成 AppIcon 深色 + 着色 1024(以及保留旧条目时所需的主屏幕尺寸)
- [ ] 7. 更新 AppIcon.appiconset/Contents.json,添加感光深色 + 着色条目
- [ ] 8. 运行 flutter build ios --simulator --debug
- [ ] 9. 运行 simctl uninstall + install;验证启动时间 <0.5s 且 Assets.car 中出现图标外观
步骤 1 — 生成启动 Logo
使用 scripts/generate_launch_logos.py。
输入:
- 源 Logo,包含深色工作室背景(典型路径
assets/logo/logo.png) - 浅色:抠除黑色 → 保留双色调品牌颜色
- 深色:相同 Alpha 遮罩,纯金色
#E0B45D(或项目主色) - 尺寸:400×363 @1x,800×727 @2x,1200×1090 @3x(根据您的 Logo 调整宽高比)
抠图公式(匹配 Flutter SplashLogo,如果存在):
alpha_out = min(255, 4 * (R + G + B), source_alpha)
输出文件到 ios/Runner/:
BrandLogo.png,[email protected],[email protected]BrandLogoNight.png,[email protected],[email protected]
步骤 2 — 捆绑资源
在 ios/Runner.xcodeproj/project.pbxproj 中:
- 为所有六个 PNG 文件添加
PBXFileReference+PBXBuildFile - 将它们列在 Runner 组中以及 Copy Bundle Resources 中
lastKnownFileType = image.png;对@2x/@3x路径使用引号
如果存在,删除 ios/Runner/Assets.xcassets/BrandLogo.imageset 和 BrandLogoNight.imageset。
构建后,确认:
# BrandLogo 不能存在于 Assets.car 中;PNG 必须存在于 Runner.app 中
find build/ios/iphonesimulator/Runner.app -name 'BrandLogo*.png'
xcrun assetutil --info build/ios/iphonesimulator/Runner.app/Assets.car | grep -i BrandLogo || true
步骤 3 — LaunchScreen.storyboard
使用现代的 IB 格式(toolsVersion ≥ 21701,useTraitCollections,能力“文档保存为 Xcode 8 格式”)。
模式(完整模板:references/launch-storyboard.md):
UIImageViewcontentMode="scaleAspectFit",图像BrandLogo- 变体:
key="userInterfaceStyle=dark" image="BrandLogoNight" - 宽度 ≈ 父视图的
0.28–0.40(从 ~0.32 开始);高度 = 宽度 × Logo 宽高比 - 中心 X/Y 约束
- 浅色背景显式 sRGB(例如象牙白
#FFFCF7) - 深色背景变体显式 sRGB(例如
#17120E) <resources>必须声明两个图像名称及其固有尺寸
Info.plist:UILaunchStoryboardName = LaunchScreen。
步骤 4 — Flutter 过渡(推荐但可选)
防止 Flutter 接管时出现白色闪烁:
- 创建
LaunchBackground.colorset,包含浅色 + 深色亮度(适用于非启动 UI) - Main.storyboard 的 ViewController 背景 → 指定为命名颜色
LaunchBackground - SceneDelegate / 自定义
FlutterViewController:在viewDidLoad/viewDidLayoutSubviews中,从UIColor(named: "LaunchBackground")设置view.backgroundColor和window.backgroundColor
步骤 5 — 应用图标外观(iOS 18+)
使用 scripts/generate_app_icon_variants.py 从 1024 营销图标(奶油色背景 + Logo)生成。
| 外观 | 图像 |
|---|---|
| 默认(任意) | 现有浅色图标 |
| 深色 | 深色底板(#17120E)上的金色 Logo,或根据 Apple HIG 使用透明背景 |
| 着色 | 灰度:黑色上的白色/灰色 Logo(系统应用着色) |
| 透明 | 从着色图标自动派生 — Contents.json 中无需条目 |
更新 AppIcon.appiconset/Contents.json — 参见 references/appicon-contents.md。
优先使用通用 1024 尺寸条目,并添加:
"appearances": [{ "appearance": "luminosity", "value": "dark" }]
"appearances": [{ "appearance": "luminosity", "value": "tinted" }]
如果项目仍在使用传统每尺寸 iPhone 条目,请保留它们;至少为 60pt @2x/@3x 和营销 1024 尺寸添加深色/着色变体。
验证:
xcrun actool ios/Runner/Assets.xcassets --compile /tmp/icons \
--platform iphonesimulator --minimum-deployment-target 15.0 \
--app-icon AppIcon --output-partial-info-plist /tmp/icon-partial.plist
xcrun assetutil --info /tmp/icons/Assets.car | grep -E 'UIAppearanceDark|ISAppearanceTintable'
构建的应用应列出带有 UIAppearanceDark 和 ISAppearanceTintable 的 AppIcon。
步骤 6 — 在模拟器上验证
flutter build ios --simulator --debug
xcrun simctl uninstall booted <bundle.id>
xcrun simctl install booted build/ios/iphonesimulator/Runner.app
# 启动:预期 Logo 在 ~0.4–0.5 秒内显示(而不是多秒空白)
# 图标:自定义 → 深色 / 着色;可能需要删除+重新安装以清除 SpringBoard 缓存
在沙盒化代理环境中,simctl 需要完整权限。
不要使用 rm -rf 清除 SplashBoard 缓存;卸载 + 重新安装会清除启动快照。
品牌默认值(可根据项目覆盖)
| 令牌 | 默认值 |
|---|---|
| 浅色启动背景 | #FFFCF7 |
| 深色启动背景 | #17120E |
| 深色 Logo 金色 | #E0B45D |
| 启动 Logo 宽度 | 屏幕宽度的 32% |
| 深色图标底板 | #17120E |
当项目使用不同的品牌十六进制值时,请询问用户。
附加资源
- 故事板 XML 模板:references/launch-storyboard.md
- AppIcon Contents.json 模板:references/appicon-contents.md
- 启动 Logo 脚本:scripts/generate_launch_logos.py
- 图标变体脚本:scripts/generate_app_icon_variants.py