本篇将讲解图片加载及特定平台图片处理.

为了更好的阅读体验 , 请点击 阅读原文

概览

Image 是用来展示图片的 widget.

系统提供着不同方式去构造 Image :

Image 支持以下图片格式 :

JPEG , PNG ,GIF , 动态 GIF , WebP , 动态WebP , BMP WBMP .

直接上示例

图中三个示例分别表示

  1. 从Assets加载图片
  2. 从网络加载图片并缓存在内存中
  3. 从网络加载图片并缓存在内存中且以渐现动画的形式展示 .

1 类似 Android 从 mipmap或drawable 下获取图片; iOS 从Assets.xcassets 中读取图片

2 常规的从网络加载图片,可选缓存在文件或者内存中.

3 移动应用中常用的图片展示效果.

Assets加载图片

Flutter 使用 pubspec.yaml文件定位项目根目录,识别app所需要的资产

示例:

1
2
3
flutter:
assets:
- assets/images/ic_link.png

注意此处资产路径是根目录下的路径.示例中assets和源码lib是同级目录

加载代码:

1
2
3
4
5
6
7
8
9
10
11
Widget build(BuildContext context) {
// ...
var imageAssets = 'assets/images/ic_link.png';
return new Image.asset(
imageAssets,
width: 150.0,
height: 150.0,
)
);
// ...
}

1
2
3
4
5
6
7
8
9
10
11
Widget build(BuildContext context) {
// ...
var imageAssets = 'assets/images/ic_link.png';
return new Image(
image: new AssetImage(imageAssets),
width: 150.0,
height: 150.0,
)
);
// ...
}

以上为加载当前项目中的资产图片.当从依赖包中加载图片时,需要加上依赖包名

例如我们的应用依赖三方包 flutter_gallery_assets ,它有着以下目录结构

  • …/pubspec.yaml
  • …/lib/ali_connors.png

我们就需要用以下代码来加载图片

1
new AssetImage('ali_connors.png', package: 'flutter_gallery_assets')

同时还需要去 pubspec.yaml 文件中申明

1
2
3
assets:
- assets/images/ic_link.png
- packages/flutter_gallery_assets/ali_connors.png

注意: ali_connors.png 文件路径其实为 flutter_gallery_assets-版本号/lib/ali_connors.png 其中lib作为三方包时是隐式包含了, __不需要__我们自己添加

File加载图片

直接上代码

1
2
3
4
5
6
7
8
9
10
11
12
Widget build(BuildContext context) {
// ...
var imagePath = '/Users/xx/Downloads/cow.png';
return new Image(
image: new FileImage(new File(imagePath)),
repeat: ImageRepeat.noRepeat,
width: 150.0,
height: 150.0,
)
);
// ...
}

注意: 这里imagePath作为绝对路径读的是计算机上的图片地址 , 找不到本机图片时不会显示 . 因为平台关系 , 相对路径一般访问不到 , 需要通过三方包 path_provider 来提供与平台无关的访问设备文件的方法.届时还需要将图片导入到设备中 ,此处就不作展开

网络加载图片

应用中网络加载图片的场景许多 , 先给出一个简单的示例:

1
2
3
4
5
6
7
8
9
10
11
Widget build(BuildContext context) {
// ...
var imgUrl = 'https://ws1.sinaimg.cn/large/006tNc79gy1fpa5bvsqskj3044048mx5.jpg';
return new Image.network(
imgUrl,
width: 150.0,
height: 150.0,
)
);
// ...
}

1
2
3
4
5
6
7
8
9
10
11
Widget build(BuildContext context) {
// ...
var imgUrl = 'https://ws1.sinaimg.cn/large/006tNc79gy1fpa5bvsqskj3044048mx5.jpg';
return new Image(
image: new NetworkImage(imgUrl),
width: 150.0,
height: 150.0,
)
);
// ...
}

这种只是简单的加载网络图片,若图片较大,或者网络卡顿.图片显示的效果就显得很突兀(可参考上面gif ) , 此时我们需要给图片呈现加一段渐现的Fading动画.

FadeInImage

FadeInImage更符合应用中的场景 , 渐现呈现网络图片,并且缓存到内存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import 'package:transparent_image/transparent_image.dart';

Widget build(BuildContext context) {
// ...
var imgUrl = 'https://ws1.sinaimg.cn/large/006tNc79gy1fpa5bvsqskj3044048mx5.jpg';
return new FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: imgUrl,
width: 150.0,
height: 150.0,
fadeInDuration: const Duration(milliseconds: 1200),
fadeOutDuration: const Duration(milliseconds: 1200),
)
);
// ...
}

示例效果请参考上面的gif效果图 , 其中用到了三方库 transparent_image 主要作用是使用其透明图片作为占位图

可使用 FadeInImage.assetNetwork 实现文件缓存. 若想实现 Android 中 Glide ,Picasso , iOS 中 Kingfisher 这样的图片三级缓存框架 , 就需要自行封装实现了.

这里我们可以发现 , 我们未主动地在Android应用清单文件中申明网络权限,Flutter默认已经授予了网络权限用以提供热部署等等.

分辨率处理

手机有不同的像素比率 , 这时就需要根据手机的像素比率来加载不同图片 . 做法很简单,只需要在图片同级目录下创建 2.0x/abc.png 和 3.0x/abc.png 的目录即可

pubspec.yaml 中定义的assets路径不需要增加 2.0x 3.0x

例如以前图片是

1
2
3
flutter:
assets:
- assets/images/ic_link.png

加入分辨率目录后不变 , 依然是该路径

特定平台图片

对于 Android , iOS 特定平台的资产图片需要我们去对应的平台文件夹下去设置 . 以下为两个常见的场景 , 我们将在Flutter框架运行前使用到图片资产

更新应用图标

更新应用图标的方式与在开发原生Android,iOS应用时一样.

Android

在项目根目录下的 .../android/app/src/main/res里,默认应用图标为ic_launcher.png ,可分别替换对应分辨率下的图片从而更新应用图标

iOS

在项目根目录下的 .../ios/Runner/Assets.xcassets/AppIcon.appiconset , 替换相应图片从而更新应用图标

更新启动页

Android

Flutter 默认设置了个启动页 .../android/app/src/main/res/drawable/launch_background.xml . 可通过修改该文件来定制个性化的元素

iOS

.../ios/Runner/Assets.xcassets/LaunchImage.imageset , 放置LaunchImage.png ,LaunchImage@2x.png , LaunchImage@3x.png. 若用到不同的文件名称 , 需要在同目录下更新 Contents.json中的文件名称

还可以通过打开…/ios/Runner.xcworkspace , 来完全定制启动屏幕storyboard .

好了, 关于 Image 的部分就讲到这里了. 相关代码已经上传 GitHub ,如有帮到你, 请不吝点个Star🤗