Flutter 可以包含 assets,asset 是打包到程序安装包中的,可在运行时访问。常见类型的 asset 包括静态数据(比如 JSON 文件),配置文件,图标和图片 (JPEG, WebP, GIF, animated WebP/GIF, PNG, BMP, WBMP)。
指定 assets
Flutter 使用 pubspec.yaml
文件来识别应用程序所需的 asset。
flutter:
assets:
- images/my_icon.png
- assets/background.png
asset 的声明顺序无关紧要,实际目录可以是任意文件夹。这些文件会被放入一个特殊的地方叫 asset bundle,可以在运行时读取。
比如根目录下有如下文件:
.../pubspec.yaml
.../graphics/my_icon.png
.../graphics/background.png
.../graphics/dark/background.png
pubspec.yaml
配置为:
flutter:
assets:
- graphics/background.png
那么 graphics/background.png
和 graphics/dark/background.png
将包含在 asset bundle 中。前者被认为是 main asset
,后者被认为是一种变体 variant
。
如果配置为:
flutter:
assets:
- graphics/
那么 graphics/my_icon.png
, graphics/background.png
和 graphics/dark/background.png
都会被放到 asset bundle 中。
在选择匹配当前设备分辨率的图片时,Flutter 使用 asset 变体。
加载 assets
通过 AssetBundle 访问 asset。
-
loadString
方法加载字符串或文本 text -
load
方法加载图片或二进制文件
加载文本 assets
每个 Flutter 应用程序都有一个 rootBundle 对象,可以访问主 asset bundle。
可以直接使用 package:flutter/services.dart
中的全局静态的 rootBundle 对象来加载asset。
但是最好使用 DefaultAssetBundle 来获取当前 BuildContext 的 AssetBundle。这种方法不是使用应用程序构建的默认 asset bundle,而是使父级 widget 在运行时替换的不同的 AssetBundle,这对于本地化或测试场景很有用。通常,可以使用 DefaultAssetBundle.of()
从应用运行时间接加载asset。
在 Widget 上下文之外,或 AssetBundle 的句柄不可用时,可以使用 rootBundle 直接加载这些 asset,例如:
import 'dart:async' show Future;
import 'package:flutter/services.dart' show rootBundle;
Future<String> loadAsset() async {
return await rootBundle.loadString('assets/config.json');
}
加载图片
Flutter 可以为当前设备加载适合其分辨率的图像。
声明分辨率相关的图片 assets
AssetImage 了解如何将逻辑请求 asset 映射到最接近当前设备像素比例的 asset。为了使这种映射起作用,应该根据特定的目录结构来保存 asset
…/image.png
…/Mx/image.png
…/Nx/image.png
其中 M 和 N 是数字标识符,对应于其中包含的图像的分辨率,也就是说,它们指定不同像素设备比例的图片,主资源默认对应于 1.0 倍的分辨率图片,比如:
…/my_icon.png
…/2.0x/my_icon.png
…/3.0x/my_icon.png
在设备像素比率为 1.8 的设备上,.../2.0x/my_icon.png
将被选择。对于 2.7 的设备像素比率,.../3.0x/my_icon.png
将被选择。
如果未在 Image 控件上指定渲染图像的宽度和高度,那么它将占用与主资源相同的屏幕空间量,只是分辨率更高。也就是说,如果 .../my_icon.png
是 ,那么 .../3.0x/my_icon.png
应该是 ,但如果未指定宽度和高度,它们都将渲染为 (以逻辑像素为单位)。
pubspec.yaml 中 asset 部分中的每一项都应与实际文件相对应,但主资源项除外。当主资源缺少某个资源时,会按分辨率从低到高的顺序去选择,即如果 1x 中没有的话会到 2x 中找,2x 中还没有的话到 3x 中找。
加载图片
Widget build(BuildContext context) {
// ...
return DecoratedBox(
decoration: BoxDecoration(
image: DecorationImage(
// 系统会根据分辨率自动选择不同大小的图片
image: AssetImage('graphics/background.png'),
// ...
),
// ...
),
);
// ...
}
使用默认的 asset bundle 加载资源时,内部会自动处理分辨率。
依赖包中的资源
资源在 pubspec.yaml
中声明
要加载依赖包中的图像,必须给 AssetImage 提供 package 参数。
假设应用程序依赖于一个名为“my_icons”的包,它具有如下目录结构:
…/pubspec.yaml
…/icons/heart.png
…/icons/1.5x/heart.png
…/icons/2.0x/heart.png
然后加载图像,使用:
AssetImage('icons/heart.png', package: 'my_icons')
包使用的本身的资源也应该加上 package 参数来获取。
资源在 lib/
包下
在 pubspec.yaml
文件中声明的资源会打包到 package 中。如果资源直接放在 lib/
文件夹且未在 pubspec.yaml
文件中声明。那么应用程序必须在自己的 pubspec.yaml
中指定包含哪些资源。比如,一个名为“fancy_backgrounds”的包,可能包含以下文件:
…/lib/backgrounds/background1.png
…/lib/backgrounds/background2.png
…/lib/backgrounds/background3.png
要使用第一张图像,必须在 pubspec.yaml
中声明:
flutter:
assets:
- packages/fancy_backgrounds/backgrounds/background1.png
lib/
是隐含的,不应该包含在路径中。
Android 中使用 Flutter 中的资源
Flutter 中有一个图标文件:
flutter:
assets:
- icons/heart.png
在 Android 代码中要使用 Flutter 的资源,从 FlutterView 中获取 PluginRegistry.Registrar,通过它的 lookupKeyForAsset 方法获取一个 key。
// registrar 是 PluginRegistry.Registrar 对象
AssetManager assetManager = registrar.context().getAssets();
String key = registrar.lookupKeyForAsset("icons/heart.png");
AssetFileDescriptor fd = assetManager.openFd(key);
Flutter 使用 Android/iOS 资源改变 icon 和 splash
替换启动图标:
Android 只要到 /android/app/src/main/res/
中替换图片即可。iOS 到 /ios/Runner/Assets.xcassets/AppIcon.appiconset
中替换即可。
替换 Splash 内容:
Android 修改 /android/app/src/main/res/drawable/launch_background.xml
文件。
iOS 要将图片添加到启动屏幕的中心,到 /ios/Runner/Assets.xcassets/LaunchImage.imageset
中拖入图片,并命名为 images LaunchImage.png、LaunchImage@2x.png、LaunchImage@3x.png。如果使用不同的文件名,还必须更新同一目录中的 Contents.json 文件。
网友评论