显示图片当然是最基础和重要的轮子,我们来看下Flutter的Image对应于安卓的Imageview是有多么的好用,封装的多实在的库。。
– Image:通过ImageProvider来加载图片
– Image.asset:用来加载本地资源图片
– Image.file:用来加载本地(File文件)图片
– Image.network:用来加载网络图片
– Image.memory:用来加载Uint8List资源(byte数组)图片
相比安卓早期需要自己弄一个库去加载,实在厚道,自动封装了对应的加载方法了。怎么使用我们看下下面代码案例
图片格式上支持: JPEG , PNG ,GIF , 动态 GIF , WebP , 动态WebP , BMP WBMP .
我们先看下demo
import 'package:flutter/material.dart';
void main() =>
runApp(ImageDemoApp());
class ImageDemoApp extends BoxStateLessWidget{
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text("Container Test"),
centerTitle: true,),
body: new ListView(
children: <Widget>[
// 资源图片
new Image.asset('imgs/logo.jpeg'),
//网络图片
new Image.network(
'https://flutter.io/images/homepage/header-illustration.png'),
//使用ImageProvider加载图片
new Image(image: new NetworkImage(
"https://flutter.io/images/homepage/screenshot-2.png"),)
],
),
);
}
}
这个简单的案例.我们看下构造函数
/// A widget that displays an image.
///
/// Several constructors are provided for the various ways that an image can be
/// specified:
///
/// * [new Image], for obtaining an image from an [ImageProvider].
/// * [new Image.asset], for obtaining an image from an [AssetBundle]
/// using a key.
/// * [new Image.network], for obtaining an image from a URL.
/// * [new Image.file], for obtaining an image from a [File].
/// * [new Image.memory], for obtaining an image from a [Uint8List].
///
/// The following image formats are supported: {@macro flutter.dart:ui.imageFormats}
///
/// To automatically perform pixel-density-aware asset resolution, specify the
/// image using an [AssetImage] and make sure that a [MaterialApp], [WidgetsApp],
/// or [MediaQuery] widget exists above the [Image] widget in the widget tree.
///
/// The image is painted using [paintImage], which describes the meanings of the
/// various fields on this class in more detail.
///
/// See also:
///
/// * [Icon], which shows an image from a font.
/// * [new Ink.image], which is the preferred way to show an image in a
/// material application (especially if the image is in a [Material] and will
/// have an [InkWell] on top of it).
class Image extends StatefulWidget {
/// Creates a widget that displays an image.
///
/// To show an image from the network or from an asset bundle, consider using
/// [new Image.network] and [new Image.asset] respectively.
///
/// The [image], [alignment], [repeat], and [matchTextDirection] arguments
/// must not be null.
///
/// Either the [width] and [height] arguments should be specified, or the
/// widget should be placed in a context that sets tight layout constraints.
/// Otherwise, the image dimensions will change as the image is loaded, which
/// will result in ugly layout changes.
///
/// If [excludeFromSemantics] is true, then [semanticLabel] will be ignored.
const Image({
Key key,
@required this.image,
this.semanticLabel,
this.excludeFromSemantics = false,
this.width,
this.height,
this.color,
this.colorBlendMode,
this.fit,
this.alignment = Alignment.center,
this.repeat = ImageRepeat.noRepeat,
this.centerSlice,
this.matchTextDirection = false,
this.gaplessPlayback = false,
}) : assert(image != null),
assert(alignment != null),
assert(repeat != null),
assert(matchTextDirection != null),
super(key: key);
对应字段
- width & height
用来指定显示图片区域的宽高(并非图片的宽高)
fit
设置图片填充,类似于Android中的ScaleType- BoxFit.contain
全图居中显示但不充满,显示原比例 - BoxFit.cover
图片可能拉伸,也可能裁剪,但是充满容器 - BoxFit.fill
全图显示且填充满,图片可能会拉伸 - BoxFit.fitHeight
图片可能拉伸,可能裁剪,高度充满 - BoxFit.fitWidth
图片可能拉伸,可能裁剪,宽度充满 - BoxFit.scaleDown
效果和contain差不多, 但是只能缩小图片,不能放大图片
- BoxFit.contain
- color & colorBlendMode
这两个属性需要配合使用,就是颜色和图片混合,就类似于Android中的Xfermode。一般少用到,贴链接,有需要时候去看下就可以了。
- alignment
用来控制图片摆放的位置
- repeat
用来设置图片重复显示(repeat-x水平重复,repeat-y垂直重复,repeat两个方向都重复,no-repeat默认情况不重复).这个做过web都明白,就是填充view时候的不同方式。
- centerSlice
设置图片内部拉伸,相当于在图片内部设置了一个.9图,但是需要注意的是,要在显示图片的大小大于原图的情况下才可以使用这个属性,要不然会报错.理由是下面这个源码:assert(sourceSize == inputSize, 'centerSlice was used with a BoxFit that does not guarantee that the image is fully visible.');
- matchTextDirection
这个需要配合Directionality进行使用
- gaplessPlayback
当图片发生改变之后,重新加载图片过程中的样式(1、原图片保留)
因此我们可以这么修改图片的显示
new Image.network(
'https://gw.alicdn.com/tfs/TB1CgtkJeuSBuNjy1XcXXcYjFXa-906-520.png',
fit: BoxFit.contain,
width: 150.0,
height: 100.0,
),
new Image.asset(
'images/logo.png',
width: 250,
height: 250,
fit: BoxFit.contain,
centerSlice:
new Rect.fromCircle(center: const Offset(20, 20), radius: 1),
)
FadeInImage
在实际开发中,考虑到图片加载速度可能不能达到预期。所以希望能增加渐入效果&增加placeHolder的功能。Flutter同样提供的这样的组件——FadeInImage。
提示
唯一有点不友好的是,添加本地图片有点麻烦,希望官方后续优化好这个问题,就是asset
文件需要把添加的图片自己手动加到pubspec.yaml
flutter:
assets:
- assets/my_icon.png
- assets/background.png
不像安卓,添加文件的drawable目录,自动有个R的id来使用。同时加载asset是自己写路径,容易出错啊。特别是图片多了之后,成千上百,那简直受不了
网络请求Image是大家最常见的操作。这里重点说明两个点:
- 缓存
ImageCache是ImageProvider默认使用的图片缓存。ImageCache使用的是LRU的算法。默认可以存储1000张图片。如果觉得缓存太大,可以通过设置ImageCache的maximumSize属性来控制缓存图片的数量。也可以通过设置maximumSizeBytes来控制缓存的大小(默认缓存大小10MB)。
- CDN优化
如果想要使用cdn优化,可以通过url增加后缀的方式实现。默认实现中没有这个点,但是考虑到cdn优化的可观收益,建议大家利用好这个优化。
ref
https://flutterchina.club/assets-and-images/
https://www.jianshu.com/p/9e6c470ea5bf