Flutter | 资源管理

2022-02-11 13:59:49 浏览数 (1)

本文示例代码地址

Flutter 安装包中会包含代码和 assets 资源两部分,Assets 是会打包到程序安装包中的,可在运行时访问。常见类型的 assets 包括静态数据,如 json ,配置文件,图片,MP3,gif 等。

加载图片

例如加载一张图片,在 Flutter 中使用 pubspec.yaml 文件来管理所需要的文件

  • 在加载图片之前,需要在根目录下创建一个文件夹,里面存放图片,以及它所对应分辨率的图片

如上图,创建了 images 文件夹,然后放入图片,并创建对应分辨率的文件夹,将图片放进去即可 注意:flutter 默认是必须要创建 2.0x 和 3.0x,至于4.0x,可自行选择

  • 图片准备好之后,就可以通过 pubspec.yaml 文件进行配置
代码语言:javascript复制
flutter:
  uses-material-design: true
  assets:
    - images/icon.png
    - images/2.0x/icon.png
    - images/3.0x/icon.png
    - images/4.0x/icon.png
  • 接着就可以显示图片了
代码语言:javascript复制
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 中。

例如

代码语言:javascript复制
.../pubspec.yaml
.../images/icon.png
.../images/2.0x/icon.png
复制代码

然后在 pubspec.yaml 中,只需要包含:

代码语言:javascript复制
flutter:
  assets:
    - images/icon.png
复制代码

那么这两个 images/icon.png 和 images/2.0x/icon.png 都将包含在 asset bundle 中。前者被认为是 main asset(主资源),后者被认为是一种变体(variant)

在选择设备当前分辨率时,Flutter 会用到 asset 变体,将来,Flutter 可能会将这种机制扩展到本地化,阅读提示等方面

因此,在上面加载图片中,pubspec.yaml 文件可以直接使用如下写法:

代码语言:javascript复制
flutter:
  uses-material-design: true
  assets:
    - images/icon.png
复制代码

加载依赖包中的资源图片

代码语言:javascript复制
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 中也应该进行声明

代码语言:javascript复制
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

代码语言:javascript复制
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 来实现自定义启动页面(你也可以直接换一张图片)
代码语言:javascript复制
<!-- 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.pngLaunchImage@2x.pngLaunchImage@3x.png。 如果你使用不同的文件名,那您还必须更新同一目录中的Contents.json文件,图片的具体尺寸可以查看苹果官方的标准。 您也可以通过打开Xcode完全自定义storyboard。在Project Navigator中导航到Runner/Runner然后通过打开Assets.xcassets拖入图片,或者通过在LaunchScreen.storyboard中使用Interface Builder进行自定义

问题

1,使用本地图片之后,需要重新运行项目,而不是启用热重载,如果使用热重载,可能会导致错误,或者是图片加载不出来

2,在 pubspec.yaml 中,一定要注意规范,避免出现多余的空格等 ,否则可能会出现异常

3,在 pubspec.yaml 中需要将所有使用到的图片全部声明出来,虽然在知道变体以后一张图片只需要写一次,但是仍然会非常麻烦,这个时候可以使用一个相对路径来标识,如:

代码语言:javascript复制
flutter:
  uses-material-design: true
  assets:
    - images/
复制代码

参考自Flutter实战(书籍)

0 人点赞