Flutter 资源文件 Adding assets and images

今天临时插播一条内容,因为在工作中有小伙伴对Flutter的assets and images有些疑问,查了查文档也不太明白,今天我们就一步一步看看Flutter的assets到底怎么使用。

Flutter应用可以同时包含代码和资产(也称为资源)。 资产是与您的应用程序捆绑和部署的文件,可在运行时访问。 资产的常见类型包括静态数据(如JSON文件),配置文件,图标和图像(JPEG,WebP,GIF,动画WebP / GIF,PNG,BMP和WBMP)。

指定资产
Flutter使用位于项目根目录的pubspec.yaml文件来标识应用程序需要的资产。

例如:

flutter:
  assets:
    - assets/my_icon.png
    - assets/background.png

有的同学可能要有疑问了

  • 文件夹的名字是固定的吗?
  • 如果这个文件夹图片特别多怎么办? 

问题1:文件夹的名字是可以更改的。

问题2:我们可以设置到目录级别,类似这样。

flutter:
  assets:
    - directory/
    - directory/subdirectory/

子目录的子目录也需要这样配置,注意要以 ‘/’结尾。

Asset bundling

Flutter中的assets部分都应该在pubspec.yaml文件资产部分中配置。在构建期间,Flutter会将资产放入Asset bundling,应用程序可在运行时从中读取。

Asset variants

构建过程支持资产变体的概念:资产的不同版本可能会在不同的上下文中显示。 在pubspec.yaml的资产部分中指定了资产路径后,构建过程将在相邻子目录中查找具有相同名称的所有文件。 然后,将这些文件与指定的资产一起包括在Asset bundling中。

例如:你的项目中是这样的

.../pubspec.yaml
.../graphics/my_icon.png
.../graphics/background.png
.../graphics/dark/background.png
...etc.

在pubspec.yaml中配置

flutter:
  assets:
    - graphics/background.png

这样,dark就已变体的形式存在了。当然,你也可以配置到目录,效果是一样的。 

flutter:
  assets:
    - graphics/

在选择适合分辨率的图像时,Flutter使用资产变体。 将来,可能会扩展此机制,以包括针对不同语言环境或区域,阅读方向等的变体。 

Loading assets

我们可以通过AssetBundle对象访问其资产。

Asset bundling允许加载字符串/文本资产loadString()或图像/二进制资产load()。在build阶段,pubspec.yaml中配置的路径,映射到logical key maps中。 

Loading text assets

每个Flutter应用程序都有一个rootBundle对象访问主资产包。 可以使用package:flutter / services.dart中的rootBundle全局静态变量直接加载资产。

但是,建议使用DefaultAssetBundle而不是应用程序构建的默认资产捆绑包来获取当前BuildContext的AssetBundle; 这种方法使父窗口小部件可以在运行时替换不同的AssetBundle,这对于本地化或测试场景很有用。

通常,您将使用DefaultAssetBundle.of()从应用程序的运行时rootBundle间接加载资产(例如JSON文件)。当然,如果在Widget上下文之外,或者当AssetBundle的句柄不可用时,您可以使用rootBundle直接加载此类资产。 例如:

import 'dart:async' show Future;
import 'package:flutter/services.dart' show rootBundle;

Future<String> loadAsset() async {
  return await rootBundle.loadString('assets/config.json');
}

Loading images

Flutter可以为当前设备的像素比率加载适合分辨率的图像。AssetImage了解选取与当前设备像素比率最接近的资产。同时我们的目录结构应该如下:

.../image.png
.../Mx/image.png
.../Nx/image.png
...etc.

其中M和N是数字标识符,对应于其中包含的图像的分辨率。 换句话说,它们指定了图像打算用于的设备像素比率。
假定主要资产对应于1.0的分辨率。 例如,对于名为my_icon.png的图像,请考虑以下资产布局:

.../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 widget上指定渲染图像的宽度和高度,则将使用标称分辨率缩放资产,以便它以更高的分辨率占用与主要资产相同的屏幕空间。 如果... / my_icon.png为72px x 72px,则... / 3.0x / my_icon.png应该为216px x 216px; 但是如果未指定width和height,它们都将渲染为72px x 72px(单位是逻辑像素),3.0x下的图片将按3.0进行缩放。

注意:设备像素比率取决于MediaQueryData.size,该参数要求使用MaterialApp或CupertinoApp作为AssetImage的祖先。每个逻辑像素的设备像素数。 这个数可能不会是二的幂。 实际上,它甚至可能不是整数。 例如,Nexus 6的装置像素比例为3.5。(实际上,我们也可以使用MediaQuery.of(context).devicePixelRatio来查看当前设备的像素比。

images实践

我准备了4张100x100的图片。

 

import 'package:flutter/material.dart';

class AssetsPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
    return Scaffold(
      appBar: AppBar(
        title: Text('测试assets 设备PixelRatio $devicePixelRatio'),
      ),
      body: Container(
        color: Colors.black,
        child: Center(
          child: Image.asset('images/img/test.jpg'),
        ),
      ),
    );
  }
}

按着文档配置好,这里没有指定到2.0x下,只是指定到了文件夹,并且文件夹的名字也经过了更改,我们来看看效果。

我们看到设备devicePixelRatio是3.0,图片显示也是正常,如果我们删除img下的x.0文件夹。在来看看效果。

因为我们使用的图片都是100x100的,并且没有设置width和height,那么按着Flutter的要求,如果我们想要在设备上显示同样的效果,3.0x中应该使用300x300的图标,应为3.0x下的图片将会缩放显示。

  assets:
    - images/img/2.0x/
    - images/img/3.0x/

这种情况下是无法正常load image的。 接下来我们恢复原来的配置,继续测试。

这是一个3.5的设备,向下选取了3.0x的图片,我们将3.0x删除在试试效果。

可以看到走到了4.0x,我们在把4.0x删除,走到了2.0x的目录中。这个结果说明,Flutter的机制中是选取距离目标像素比例最接近的目录。当然笔者还做了好多测试,比如1.9x,2.0x等等,感兴趣的同学可以自己试一试,对于这部分的源码,会在会许文章中更新,小伙伴不要着急,今天这个部分也只是项目遇到应急写出来的,欢迎大家指正。接下来的文章还是会继续将常用Widget逐一介绍,在最后的系列中,会公开一个商业级的项目,感兴趣的小伙伴关注。如果您在阅读过程中发现错误,请及时留言给我,我会第一时间改正。也欢迎大家一切交流,共同进步,感谢支持!

猜你喜欢

转载自blog.csdn.net/z2008q/article/details/108580515