添加资源和图像
如何在你的 Flutter 应用中使用图像(和其他资源)。
Flutter 应用可以包含代码和资源(有时也称为资源)。 资源是与你的应用捆绑和部署的文件,可在运行时访问。 常见的资源类型包括静态数据(例如 JSON 文件)、配置文件、图标和图像(JPEG、WebP、GIF、动画 WebP/GIF、PNG、BMP 和 WBMP)。
指定资源
#Flutter 使用 pubspec.yaml 文件(位于你的项目根目录下)来识别应用所需的资源。
这是一个例子
flutter:
assets:
- assets/my_icon.png
- assets/background.png
要包含目录下的所有资源,请使用 / 字符指定目录名称
flutter:
assets:
- directory/
- directory/subdirectory/
资源打包
#flutter 部分的 assets 子部分指定应与应用一起包含的文件。 每个资源通过一个显式路径(相对于 pubspec.yaml 文件)标识,该路径指示资源文件的位置。 资源的声明顺序无关紧要。 使用的实际目录名称(第一个示例中的 assets 或上述示例中的 directory)无关紧要。
在构建期间,Flutter 将资源放入一个特殊的存档中,称为资源包,应用在运行时从中读取资源。
构建时自动转换资源文件
#Flutter 支持使用 Dart 包在构建应用时转换资源文件。 为此,请在 pubspec 文件中指定资源文件和转换器包。 要了解如何执行此操作以及编写自己的资源转换包,请参阅 构建时转换资源。
加载资源
#你的应用可以通过 AssetBundle 对象访问其资源。
资源包上的两个主要方法允许你加载字符串/文本资源 (loadString()) 或图像/二进制资源 (load()) 到包中,给定一个逻辑键。 逻辑键映射到在构建时在 pubspec.yaml 文件中指定的资源的路径。
加载文本资源
#每个 Flutter 应用都有一个 rootBundle 对象,以便轻松访问主资源包。 可以直接使用 package:flutter/services.dart 中的 rootBundle 全局静态变量加载资源。
但是,建议使用 DefaultAssetBundle 获取当前 BuildContext 的 AssetBundle,而不是使用与应用一起构建的默认资源包;这种方法允许父小部件在运行时替换不同的 AssetBundle,这对于本地化或测试场景非常有用。
通常,你将使用 DefaultAssetBundle.of() 间接加载资源,例如从应用的运行时 rootBundle 加载 JSON 文件。
在 Widget 上下文之外,或者当无法使用 AssetBundle 的句柄时,你可以使用 rootBundle 直接加载这些资源。 例如
import 'package:flutter/services.dart' show rootBundle;
Future<String> loadAsset() async {
return await rootBundle.loadString('assets/config.json');
}
加载图像
#要加载图像,请在小部件的 build() 方法中使用 AssetImage 类。
例如,你的应用可以从上一个示例中的资源声明加载背景图像
return const Image(image: AssetImage('assets/background.png'));
感知分辨率的图像资源
#Flutter 可以加载适合当前 设备像素比 的图像。
AssetImage 将逻辑请求的资源映射到与当前 设备像素比 最匹配的资源。
要使此映射工作,应根据特定的目录结构排列资源
.../image.png
.../Mx/image.png
.../Nx/image.png
...etc.
其中 M 和 N 是数值标识符,对应于包含在其中的图像的标称分辨率。 换句话说,它们指定图像打算用于的设备像素比。
在此示例中,image.png 被视为主资源,而 Mx/image.png 和 Nx/image.png 被视为变体。
主资源假定对应于 1.0 的分辨率。 例如,考虑为名为 my_icon.png 的图像定义的以下资源布局
.../my_icon.png (mdpi baseline)
.../1.5x/my_icon.png (hdpi)
.../2.0x/my_icon.png (xhdpi)
.../3.0x/my_icon.png (xxhdpi)
.../4.0x/my_icon.png (xxxhdpi)
在设备像素比为 1.8 时,选择资源 .../2.0x/my_icon.png。 对于设备像素比 2.7,选择资源 .../3.0x/my_icon.png。
如果未在 Image 小部件上指定渲染图像的宽度和高度,则使用标称分辨率来缩放资源,以便它占用与主资源相同数量的屏幕空间,只是分辨率更高。 也就是说,如果 .../my_icon.png 是 72px x 72px,那么 .../3.0x/my_icon.png 应该是 216px x 216px;但如果未指定宽度和高度,它们都渲染为 72px x 72px(以逻辑像素为单位)。
捆绑感知分辨率的图像资源
#你只需要在 pubspec.yaml 的 assets 部分中指定主资源或其父目录。 Flutter 会为你捆绑变体。 每个条目应对应于真实文件,主资源条目除外。 如果主资源条目不对应于真实文件,则分辨率最低的资源将用作低于该分辨率的设备的后备选项。 但是,该条目仍然应包含在 pubspec.yaml 清单中。
使用默认资源包的任何内容都会在加载图像时继承感知分辨率。 (如果你使用一些较低级别的类(例如 ImageStream 或 ImageCache),你也会注意到与比例相关的参数。)
包依赖项中的资源图像
#要从 包 依赖项加载图像,必须将 package 参数提供给 AssetImage。
例如,假设你的应用程序依赖于名为 my_icons 的包,该包具有以下目录结构
.../pubspec.yaml
.../icons/heart.png
.../icons/1.5x/heart.png
.../icons/2.0x/heart.png
...etc.
要加载图像,请使用
return const AssetImage('icons/heart.png', package: 'my_icons');
包本身使用的资源也应使用上述 package 参数获取。
捆绑包资源
#如果所需的资源在包的 pubspec.yaml 文件中指定,则它将自动与应用程序捆绑在一起。 特别是,包本身使用的资源必须在它的 pubspec.yaml 中指定。
包还可以选择在它的 lib/ 文件夹中拥有未在它的 pubspec.yaml 文件中指定的资源。 在这种情况下,要将这些图像捆绑在一起,应用程序必须在它的 pubspec.yaml 中指定要包含哪些图像。 例如,名为 fancy_backgrounds 的包可以具有以下文件
.../lib/backgrounds/background1.png
.../lib/backgrounds/background2.png
.../lib/backgrounds/background3.png
要包含,例如,第一张图像,应用程序的 pubspec.yaml 应在 assets 部分中指定它
flutter:
assets:
- packages/fancy_backgrounds/backgrounds/background1.png
隐式包含 lib/,因此不应将其包含在资源路径中。
如果你正在开发一个包,要加载包中的资源,请在包的 pubspec.yaml 中指定它
flutter:
assets:
- assets/images/
要加载包中的图像,请使用
return const AssetImage('packages/fancy_backgrounds/backgrounds/background1.png');
与底层平台共享资源
#Flutter 资源可以使用 Android 上的 AssetManager 和 iOS 上的 NSBundle 供平台代码使用。
在 Android 中加载 Flutter 资源
#在 Android 上,资源可以通过 AssetManager API 访问。 在例如 openFd 中使用的查找键是从 PluginRegistry.Registrar 或 FlutterView 上的 lookupKeyForAsset 或 getLookupKeyForAsset 获取的。 PluginRegistry.Registrar 在开发插件时可用,而 FlutterView 是包含平台视图的应用程序的选择。
例如,假设你在 pubspec.yaml 中指定了以下内容
flutter:
assets:
- icons/heart.png
这反映了你的 Flutter 应用程序中的以下结构。
.../pubspec.yaml
.../icons/heart.png
...etc.
要从你的 Java 插件代码访问 icons/heart.png,请执行以下操作
AssetManager assetManager = registrar.context().getAssets();
String key = registrar.lookupKeyForAsset("icons/heart.png");
AssetFileDescriptor fd = assetManager.openFd(key);
在 iOS 中加载 Flutter 资源
#在 iOS 上,资源可以通过 mainBundle 获取。例如在 pathForResource:ofType: 中使用的查找键,可以从 FlutterPluginRegistrar 上的 lookupKeyForAsset 或 lookupKeyForAsset:fromPackage:,或者从 FlutterViewController 上的 lookupKeyForAsset: 或 lookupKeyForAsset:fromPackage: 获取。FlutterPluginRegistrar 在开发插件时可用,而 FlutterViewController 在开发包含平台视图的应用时是更好的选择。
例如,假设您拥有上述 Flutter 设置。
要从您的 Objective-C 插件代码中访问 icons/heart.png,您将执行以下操作
NSString* key = [registrar lookupKeyForAsset:@"icons/heart.png"];
NSString* path = [[NSBundle mainBundle] pathForResource:key ofType:nil];
要从您的 Swift 应用中访问 icons/heart.png,您将执行以下操作
let key = controller.lookupKey(forAsset: "icons/heart.png")
let mainBundle = Bundle.main
let path = mainBundle.path(forResource: key, ofType: nil)
有关更完整的示例,请参阅 pub.dev 上的 Flutter video_player 插件 的实现。
在 Flutter 中加载 iOS 图像
#在通过 将 Flutter 添加到现有的 iOS 应用 实现 Flutter 时,您可能在 iOS 中托管了想要在 Flutter 中使用的图像。为此,使用 平台通道 将图像数据作为 FlutterStandardTypedData 传递给 Dart。
平台资源
#在平台项目中直接使用资源还有其他情况。以下是两种常见情况,即在 Flutter 框架加载和运行之前使用资源。
更新应用图标
#更新 Flutter 应用程序的启动图标与更新原生 Android 或 iOS 应用程序中的启动图标相同。
![]()
Android
#在您的 Flutter 项目的根目录中,导航到 .../android/app/src/main/res。各种位图资源文件夹,例如 mipmap-hdpi,已经包含名为 ic_launcher.png 的占位符图像。根据 Android 开发者指南 中指示的屏幕密度,用您想要的资源替换它们,并尊重推荐的图标大小。
![]()
iOS
#在您的 Flutter 项目的根目录中,导航到 .../ios/Runner。Assets.xcassets/AppIcon.appiconset 目录已经包含占位符图像。根据 Apple 人机界面指南 规定的文件名替换它们,并使用适当大小的图像。保留原始文件名。
![]()
更新启动屏幕
#
Flutter 还使用原生平台机制为您的 Flutter 应用绘制过渡启动屏幕,直到 Flutter 渲染应用程序的第一帧为止。此启动屏幕将持续存在,直到 Flutter 渲染应用程序的第一帧。
Android
#要添加启动屏幕(也称为“闪屏”)到您的 Flutter 应用程序,请导航到 .../android/app/src/main。在 res/drawable/launch_background.xml 中,使用此 图层列表可绘制对象 XML 来自定义启动屏幕的外观。现有的模板提供了一个将图像添加到白色闪屏中间的示例代码,注释掉了。您可以取消注释它或使用其他 可绘制对象 以实现预期的效果。
有关更多详细信息,请参阅 将闪屏添加到您的 Android 应用。
iOS
#要将图像添加到“闪屏”的中心,请导航到 .../ios/Runner。在 Assets.xcassets/LaunchImage.imageset 中,放入名为 LaunchImage.png、LaunchImage@2x.png、LaunchImage@3x.png 的图像。如果您使用不同的文件名,请更新同一目录中的 Contents.json 文件。
您还可以通过在 Xcode 中打开 .../ios/Runner.xcworkspace 来完全自定义您的启动屏幕故事板。在项目导航器中导航到 Runner/Runner,并通过打开 Assets.xcassets 放入图像,或使用界面生成器在 LaunchScreen.storyboard 中进行任何自定义。
有关更多详细信息,请参阅 将闪屏添加到您的 iOS 应用。