Flutter | 资源管理

0005b72e6a0746b0be300e6117d1595b_tplv-k3u1fbpfcp-zoom-1
本文示例代码地址

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

加载图片

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

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

    image-20210113225930811

    如上图,创建了 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("加载图片"),
              )
            ],
          ),
        );
      }
    }
    
    

    效果如下所示

    345

分辨率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中进行声明

效果如下:

345

设置 APP 图标

更新 Flutter 应用程序启动图标的方式与在本机 Android 或 iOS 中 更新图标的方式相同

  • Android

    在 flutter 根目录中,找到 .../android/app/src/main/res 目录,例包含了各种资源文件夹,如 mipmap 等,找到名字为 ic_launcher.png 的图片,然后替换即可,注意,需要遵守每种屏幕密度(dpi)的建议图标大小标准即可

    image-20210118143631561
  • iOS

    在 Flutter 项目中,导航到 .../ios/Runner 。该目录中 Assets.xcassets/AppIcon.appiconset 已经包含占位符图片。主需要将他们替换为适当大小的图片,保留原始文件名称

    image-20210118144026288

更新启动页

在 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>
    
    345
  • iOS

    要将图片添加到 启动屏幕,请导航至 .../ios/Runner。在 Assets.xcassets/**LaunchImage.imageset。 ,拖入图片,并命名为LaunchImage.png[email protected][email protected]。 如果你使用不同的文件名,那您还必须更新同一目录中的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/

参考自 Flutter实战(书籍)

猜你喜欢

转载自blog.csdn.net/baidu_40389775/article/details/112783881