Flutter 安装包中会包含代码和 assets 资源两部分,Assets 是会打包到程序安装包中的,可在运行时访问。常见类型的 assets 包括静态数据,如 json ,配置文件,图片,MP3,gif 等。
加载图片
例如加载一张图片,在 Flutter 中使用 pubspec.yaml 文件来管理所需要的文件
在加载图片之前,需要在根目录下创建一个文件夹,里面存放图片,以及它所对应分辨率的图片
如上图,创建了 images 文件夹,然后放入图片,并创建对应分辨率的文件夹,将图片放进去即可
注意:flutter 默认是必须要创建 2.0x 和 3.0x,至于4.0x,可自行选择
图片准备好之后,就可以通过 pubspec.yaml 文件进行配置
flutter: uses-material-design: true assets: - images/icon.png - images/2.0x/icon.png - images/3.0x/icon.png - images/4.0x/icon.png
接着就可以显示图片了
class AssetsLoad extends StatefulWidget { @override State<StatefulWidget> createState() { return _AssetsLoadState(); } } class _AssetsLoadState extends State<AssetsLoad> { var imageID = ""; void uploadImage() { setState(() { imageID = "images/icon.png"; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("资源加载"), ), body: Column( children: [ Center( child: Container( child: Image.asset("$imageID", fit: BoxFit.cover), width: 100, height: 100, ), ), RaisedButton( onPressed: () { uploadImage(); }, child: Text("加载图片"), ) ], ), ); } }
效果如下所示
分辨率2.0x,3.0x,4.0x
当设备像素比(device pixel ratio) < 1 时候,images/icon.png 的图片将会被使用。
当设备像素比 1 < (device pixel ratio) < 2 时候,images/2.0x/icon.png 的图片将会被使用。
当设备像素比 2 < (device pixel ratio) < 3 时候,images/3.0x/icon.png 的图片将会被使用,
当 > 3 的时候,4.0x 中的图片会被调用
Flutter 最终会根据设备像素比例,去获取对应分辨率的图片
pubspec.yaml 中 asset 部分中的每一项应与实际文件相对应,但是主资源除外,当主资源缺少某个文件时,会按照分辨率从低到高的顺序去选择。
Asset 变体(variant)
构建过程支持变体概念:不同版本的 asset 可能会显示在不同的上下文中。在 pubspec.yaml 的 assets 部分指定路径时,构建过程中,会在相邻的子目录去查找具有相同名称的任何文件,这些文件随后会与指定的 asset 一起被包含在 asset bundle 中。
例如
.../pubspec.yaml .../images/icon.png .../images/2.0x/icon.png
然后在 pubspec.yaml 中,只需要包含:
flutter: assets: - images/icon.png
那么这两个 images/icon.png 和 images/2.0x/icon.png 都将包含在 asset bundle 中。前者被认为是 main asset(主资源),后者被认为是一种变体(variant)
在选择设备当前分辨率时,Flutter 会用到 asset 变体,将来,Flutter 可能会将这种机制扩展到本地化,阅读提示等方面
因此,在上面加载图片中,pubspec.yaml 文件可以直接使用如下写法:
flutter: uses-material-design: true assets: - images/icon.png
加载依赖包中的资源图片
new Image.asset('icons/heart.png', package: 'my_icons')
例如,如果要加载一个名字为 fancy_backgrounds 的包,那么他的资源文件应该是
…/lib/backgrounds/background1.png
…/lib/backgrounds/background2.png
…/lib/backgrounds/background3.png
而对应的在 pubspec.yaml 中也应该进行声明
flutter: assets: - packages/fancy_backgrounds/backgrounds/background1.png
加载文本assets
通过 rootBundle 对象加载,每个 Flutter 都有一个 rootBundle 对象,通过他可以轻松访问主资源包,直接使用 package:flutter/services.dart 中全局的 rootBundle 对象来加载 assets 即可
通过 DefaultAssetBundle来加载,建议使用 DefaultAssetBundle 来获取当前 BuildContext 的 AssetBundle 。
这种方法不是使用应用程序构建默认的 asset bundle,而是使用父级 widget 在运行时动态替换不同的 AssetBundle,这对本地化或测试场景会很有用
通常可以使用 DefalutAssetBundle.of()在应用运行时来间接加载 asset(例如 json 文件),而在 widget 上下文之外,或者其他 AssetBundle 不可用时, 可以使用 routBundle直接加载 asset
class AssetsLoad extends StatefulWidget { @override State<StatefulWidget> createState() { return _AssetsLoadState(); } } class _AssetsLoadState extends State<AssetsLoad> { var imageID = ""; var text = ""; void uploadImage() { setState(() { imageID = "images/icon.png"; }); } Future<String> loadText() async { return await rootBundle.loadString("assets/file.txt"); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("资源加载"), ), body: Column( children: [ //....... Container( child: Center( child: Text( text, textAlign: TextAlign.center, ), ), width: 100, height: 100, ), RaisedButton( onPressed: () { loadText().then((value) { setState(() { text = value; }); }); }, child: Text("加载文本"), ) ], ), ); } }
如上所示,调用 loadText 可以获取到文件中的内容,注意,该文件需要在 pubspec.yaml中进行声明
效果如下:
设置 APP 图标
更新 Flutter 应用程序启动图标的方式与在本机 Android 或 iOS 中 更新图标的方式相同
Android
在 flutter 根目录中,找到 .../android/app/src/main/res 目录,例包含了各种资源文件夹,如 mipmap 等,找到名字为 ic_launcher.png 的图片,然后替换即可,注意,需要遵守每种屏幕密度(dpi)的建议图标大小标准即可
iOS
在 Flutter 项目中,导航到 .../ios/Runner 。该目录中 Assets.xcassets/AppIcon.appiconset 已经包含占位符图片。主需要将他们替换为适当大小的图片,保留原始文件名称
更新启动页
在 Flutter 框架加载时,Flutter 会使用本地机制绘制启动项,此启动页将持续到 Flutter 渲染应用程序的第一帧时
这意味着如果你不在应用程序的 main() 方法中调用 runApp函数 (或者更具体的说,如果你不调用 window.render去响应window.onDrawFrame) 的话,启动屏幕将永远显示
Android
要将启动屏幕 (splash screen) 添加到您的 Flutter 程序,请导航至 .../android/app/src/main,在 res/drawable/launch_background.xml,通过自定义 drawable 来实现自定义启动页面(你也可以直接换一张图片)
<!-- Modify this file to customize your launch splash screen --> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="?android:colorBackground" /> <!-- You can insert your own image assets here --> <item> <bitmap android:gravity="center" android:src="@drawable/launch_image" /> </item> </layer-list>
iOS
要将图片添加到 启动屏幕,请导航至 .../ios/Runner。在 Assets.xcassets/**LaunchImage.imageset。 ,拖入图片,并命名为LaunchImage.png、LaunchImage@2x.png、LaunchImage@3x.png。 如果你使用不同的文件名,那您还必须更新同一目录中的Contents.json文件,图片的具体尺寸可以查看苹果官方的标准。
您也可以通过打开Xcode完全自定义storyboard。在Project Navigator中导航到Runner/Runner然后通过打开Assets.xcassets拖入图片,或者通过在LaunchScreen.storyboard中使用Interface Builder进行自定义
问题
1,使用本地图片之后,需要重新运行项目,而不是启用热重载,如果使用热重载,可能会导致错误,或者是图片加载不出来
2,在 pubspec.yaml 中,一定要注意规范,避免出现多余的空格等 ,否则可能会出现异常
3,在 pubspec.yaml 中需要将所有使用到的图片全部声明出来,虽然在知道变体以后一张图片只需要写一次,但是仍然会非常麻烦,这个时候可以使用一个相对路径来标识,如:
flutter: uses-material-design: true assets: - images/