定制 Google Maps Flutter 示例工程的 iOS 启动画面(Launch Screen):LaunchImage.imageset 资源替换完全指南
【免费下载链接】packagesA collection of useful packages maintained by the Flutter team项目地址: https://gitcode.com/GitHub_Trending/pac/packages
iOS 应用在进程启动、Flutter 引擎完成首帧渲染之前,系统会先展示一个由原生层提供的“启动画面”(Launch Screen)。本文以 Flutter 官方仓库中google_maps_flutter插件示例工程(google_maps_flutter_example)的 iOS Runner 工程为实例,讲解LaunchImage.imageset资源目录的结构、工作原理与两种定制方法:直接替换图片文件,或通过 Xcode 可视化操作。读完本文,你将掌握如何为任何 Flutter iOS 工程替换启动画面资源,并理解从Info.plist到LaunchScreen.storyboard再到Assets.xcassets的完整调用链。
关联文档与工程位置
本文依据的原始文档位于:
LaunchImage.imageset/README.md
该文档位于google_maps_flutter示例应用的 iOS Runner 工程中。整个示例工程通过 example/pubspec.yaml 以路径依赖(path: ../)的方式直接引用同仓库的google_maps_flutter插件源码,是插件官方自带的演示 App,其 iOS 工程结构完全遵循 Flutter 官方模板,因此本文的方法对任意 Flutter 项目同样适用。
iOS 启动画面机制简述
iOS 启动画面(Launch Screen)是 App 被系统拉起后立即显示的静态画面,用于掩盖引擎与首帧之间的加载空白期。在 Flutter 工程中,这一阶段发生在 Dart VM 初始化与首帧渲染之前,因此启动画面必须由 iOS 原生层提供,无法用 Flutter Widget 实现。
在示例工程的 Info.plist 中可以看到关键声明:
<key>UILaunchStoryboardName</key> <string>LaunchScreen</string>UILaunchStoryboardName指定了系统在启动时加载的 Storyboard 名称LaunchScreen,对应文件为 Runner/Base.lproj/LaunchScreen.storyboard。该 Storyboard 内部又通过<image name="LaunchImage" .../>引用资源目录(imageset)中的图片,最终指向Assets.xcassets/LaunchImage.imageset/目录中的图片文件。完整链路为:
Info.plist (UILaunchStoryboardName=LaunchScreen) → Base.lproj/LaunchScreen.storyboard → Assets.xcassets/LaunchImage.imageset/*.png同时,Runner.xcodeproj/project.pbxproj 的PBXResourcesBuildPhase中将LaunchScreen.storyboard与Assets.xcassets均列入资源构建阶段,确保两者被打包进Runner.app。
LaunchImage.imageset 目录结构剖析
当前目录结构如下:
Runner/Assets.xcassets/LaunchImage.imageset/ ├── Contents.json ├── LaunchImage.png # 1x 基准图(当前为 1×1 占位图) ├── LaunchImage@2x.png # 2x 高清图(当前为 1×1 占位图) ├── LaunchImage@3x.png # 3x 超高清图(当前为 1×1 占位图) └── README.md # 定制说明文档其中的 Contents.json 是 Xcode Asset Catalog 的清单文件,将三张物理图片按设备像素比(scale)映射为同一个逻辑图片资源:
{ "images" : [ { "idiom" : "universal", "filename" : "LaunchImage.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "LaunchImage@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "LaunchImage@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } }字段说明:
| 字段 | 含义 | 本工程取值 |
|---|---|---|
idiom | 目标设备类别 | universal(所有 iOS 设备) |
filename | 对应图片文件 | LaunchImage.png/LaunchImage@2x.png/LaunchImage@3x.png |
scale | 像素密度档位 | 1x(非 Retina)/2x(Retina)/3x(Super Retina) |
info.version | 清单格式版本 | 1 |
info.author | 生成工具 | xcode |
当前仓库中的三张占位图均为 1×1 像素(68 字节)的空白图,是 Flutter 模板生成的默认占位资源——这正是需要被替换的对象。
LaunchScreen.storyboard 如何引用启动图片
LaunchScreen.storyboard 中通过UIImageView展示启动图片,关键片段如下:
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4"> </imageView>两个关键点:
image="LaunchImage":这里的名称必须与 imageset 目录名LaunchImage.imageset保持一致,Xcode 据此在 Asset Catalog 中查找对应资源。contentMode="center":图片以原始尺寸居中显示,不会被拉伸铺满。Storyboard 中通过两条 Auto Layout 约束(centerX/centerY)将UIImageView固定在屏幕正中。
此外,Storyboard 的<resources>段声明了图片的逻辑尺寸(width="168" height="185"),这是 Flutter 模板预设的参考尺寸;当替换图片后,实际展示尺寸以新图片为准。由于是center模式,若希望图片铺满全屏,需要修改contentMode(例如改为scaleAspectFill或scaleToFill)或改用LaunchScreen.storyboard中的背景色方案(当前背景色为纯白red="1" green="1" blue="1")。
定制方法一:直接替换图片文件(推荐,无需 Xcode)
按原文档描述,最直接的方式是用你自己的启动图替换该目录下的图片文件。操作要点:
- 准备三张不同像素密度的图片,或至少准备一张
@2x图:LaunchImage.png→ 逻辑尺寸 × 1(非 Retina 设备)LaunchImage@2x.png→ 逻辑尺寸 × 2(主流 Retina 设备)LaunchImage@3x.png→ 逻辑尺寸 × 3(高密度设备)
- 保持文件名与 Contents.json 中的
filename字段完全一致(LaunchImage.png、LaunchImage@2x.png、LaunchImage@3x.png)。 - 重新构建运行 iOS 工程,系统即会在启动时展示新图片。
替换前建议确认图片格式:iOS 启动图支持 PNG、JPEG 等常见位图格式,工程默认使用 PNG。需要提醒的是,当前目录中的占位图是 1×1 空白图,若不替换,启动画面将显示纯色背景(Storyboard 中设置的白色背景),因此定制启动画面是每个 Flutter iOS 应用上线前的必要步骤。
定制方法二:通过 Xcode 可视化操作
原文档同时给出了第二种方式——在 Xcode 中拖拽替换,操作步骤如下:
在终端打开工程的 Xcode 工作区:
open ios/Runner.xcworkspace在 Xcode 左侧Project Navigator中展开
Runner→Runner→Assets.xcassets。选中
LaunchImage(位于LaunchImage.imageset内)。将准备好的图片从 Finder 直接拖入Xcode 右侧属性面板中对应的
1x、2x、3x插槽。
Xcode 会自动完成两件事:更新 Contents.json 中的文件名引用,并把图片复制进 imageset 目录。这种方式对不熟悉命令行或希望直观预览效果的开发者更为友好。
两种方式的等价性与取舍
两种方式在原理上是完全等价的——最终都是修改Assets.xcassets/LaunchImage.imageset/目录下的图片文件与清单。区别仅在于操作入口:
| 对比维度 | 直接替换文件 | Xcode 拖拽 |
|---|---|---|
| 依赖工具 | 任意文件管理器 / 命令行 | 需要安装 Xcode |
| 多倍图管理 | 手动维护三个文件与命名 | 可视化分配到 1x/2x/3x 插槽 |
| 清单文件更新 | 文件名不变时无需改动 | 由 Xcode 自动维护 |
| 适合场景 | CI 脚本、批量替换、版本化控制 | 日常开发、快速预览效果 |
对于插件仓库这类以代码为核心的工程,直接替换文件的方式更容易纳入版本控制与自动化流程;而 Xcode 可视化方式适合快速迭代设计稿。
启动画面定制的实用建议
结合示例工程的 Storyboard 与资源结构,定制时建议注意:
- 保持三档密度齐全:虽然系统允许缺失某档位并自动缩放,但为保证不同设备上的清晰度,建议
1x/2x/3x均提供对应尺寸的图片,避免 Retina 设备上出现模糊。 - 注意
contentMode="center"的限制:默认居中显示且不缩放,若启动图设计为全屏背景,需要同步修改 LaunchScreen.storyboard 中UIImageView的contentMode,或借助 Auto Layout 约束将图片拉伸至与父视图等宽等高。 - 考虑不同设备屏幕比例:Storyboard 启动图会随设备屏幕比例自适应容器;使用固定尺寸图片时,不同机型可能出现留白,建议在设计阶段就考虑安全区与主流屏幕比例。
- 不要混淆启动图与应用图标:应用图标由同级的
AppIcon.appiconset管理(目录结构见 Runner/Assets.xcassets),两者职责不同,替换时注意区分。 - 启动画面与首帧的衔接:在
google_maps_flutter示例中,Flutter 首帧由 AppDelegate.swift 初始化的引擎渲染(该文件同时负责注入 Google Maps API Key),启动画面消失后立即进入地图界面,因此建议启动图视觉风格与地图界面保持过渡自然。
小结
LaunchImage.imageset是 Flutter iOS 工程启动画面的核心资源目录,通过Contents.json将三档像素密度图片绑定为统一的LaunchImage逻辑资源,再由LaunchScreen.storyboard与Info.plist的UILaunchStoryboardName完成系统级装配。替换目录中的图片文件,或借助 Xcode 的open ios/Runner.xcworkspace可视化拖拽,即可完成定制。本文以google_maps_flutter官方示例工程的真实文件为依据,所有路径与配置均可直接在仓库中核对与复用。
【免费下载链接】packagesA collection of useful packages maintained by the Flutter team项目地址: https://gitcode.com/GitHub_Trending/pac/packages
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考