前言
图片是一个我们又爱又恨的东西,它是万美之本,也是万恶之源
为阐述清楚Image的使用,专开本文,希望通过本文,你可以学到一个很有用的方法
另外通过最后布局海贼王的悬赏令,基本实现可改头像,名字,悬赏的效果,可缩放
1.Image的简单认识
1.1:Image的属性
首先Image作为组件存在于
widgets/image.dart
,dart.ui里也有个Image类,别导错了
其次,Image作为一个有状态的组件,继承自StatefulWidget ,所有属性如下:
class Image extends StatefulWidget {
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,
this.filterQuality = FilterQuality.low,//滤镜质量
}) : assert(image != null),
assert(alignment != null),
assert(repeat != null),
assert(filterQuality != null),
assert(matchTextDirection != null),
super(key: key);
final ImageProvider image;
final double width;
final Color color;
final BlendMode colorBlendMode;
final BoxFit fit;
final AlignmentGeometry alignment;
final ImageRepeat repeat;
final Rect centerSlice;
final bool matchTextDirection;
final bool gaplessPlayback;
final String semanticLabel;
final bool excludeFromSemantics;
1.2.Image对象的创建
根据不同需求,一共有五种创建Image组件对象的方法
const Image({Key key,@required this.image,//通过ImageProvider创建
Image.network( String src, {//通过网络资源创建
Image.file(File file, { //通过文件创建
Image.asset(String name, //通过资源文件创建
Image.memory(Uint8List bytes, //通过内存创建
1.3:资源图片的访问
在
Image.asset
中有一大段注释介绍如何flutter中使用资源图片
var img = Image.asset(
'images/icon_head.png',
width: 50,
height: 50,
);
1.4:Image的状态
Image是一个有状态的组件,这点确实出乎我意料,我们看看他的状态有哪些
class _ImageState extends State<Image> {
ImageStream _imageStream;
ImageInfo _imageInfo;
bool _isListeningToStream = false;
bool _invertColors;
2.Image的属性表现
2.1:Image的宽高
将3:2的图片放在一个200*200的容器里,表现效果如下
var img = Image.asset(
'images/ls.jpg',
width: 100,
height: 100,
);
var imgContainer=Container(
width: 200,
height: 200,
color: Colors.cyanAccent,
child: img,
);
其中可以看出:
1.默认情况下图像会显示完全
2.这里Container定义的长宽,可见Image的长宽是无效的
3.Image组件占据的布局空间并非仅是图片!
2.2: 图片的适应模式:fit
为了方便对比,这里写了一个方法批量生成,可以看出各种模式的特性。
var fitMode = [BoxFit.none, BoxFit.contain, BoxFit.cover,
BoxFit.fill, BoxFit.fitHeight, BoxFit.fitWidth, BoxFit.scaleDown
];
//循环生成Image控件
form() {
var imgLi = <Widget>[];
fitMode.forEach((fit) {
var img = Container(
margin: EdgeInsets.all(10),
width: 150,
height: 60,
color: randomRGB(),
child: Image(
image: AssetImage("images/ls.jpg"),
fit: fit,
));
imgLi.add(Column(
children: <Widget>[img, Text(fit.toString())],
));
});
return imgLi;
}
var imgBox = Wrap(
children: form(),
);
Color randomRGB() {
Random random = new Random();
int r = 30 + random.nextInt(200);
int g = 30 + random.nextInt(200);
int b = 30 + random.nextInt(200);
return Color.fromARGB(255, r, g, b);
}
-
宽高比2:3测试结果
: -
宽高比3:2测试结果
:
图片小于容器尺寸下的测试结果
根据图片看一下,应该不言而喻了。
2.3:颜色以及混合模式:color,colorBlendMode
同样,也是批量测试一下,一图胜千言,而且感觉高大上一点
这里使用蓝色和头像进行叠合,效果如下:
![](data:image/svg+xml;utf8,<?xml version="1.0"?>)
//混合模式数组
var colorBlendMode = [
BlendMode.clear,BlendMode.src,BlendMode.dst,
BlendMode.srcOver,BlendMode.dstOver,BlendMode.srcIn,
BlendMode.dstIn,BlendMode.srcOut,BlendMode.dstOut,
BlendMode.srcATop,BlendMode.dstATop,BlendMode.xor,
BlendMode.plus, BlendMode.modulate,BlendMode.screen,
BlendMode.overlay,BlendMode.darken,BlendMode.lighten,
BlendMode.colorDodge,BlendMode.colorBurn,BlendMode.hardLight,
BlendMode.softLight,BlendMode.difference,BlendMode.exclusion,
BlendMode.multiply,BlendMode.hue,BlendMode.saturation,
BlendMode.color, BlendMode.luminosity,
];
//循环生成Image控件
formImgsColorBlendMode() {
var imgLi = <Widget>[];
colorBlendMode.forEach((mode) {
var img = Container(
margin: EdgeInsets.all(5),
width:60,
height: 60,
child: Image(
image: AssetImage("images/icon_head.png"),
color: Colors.blue,
colorBlendMode: mode,
));
imgLi.add(Column(children: <Widget>[
img,
Text(mode.toString().split(".")[1])
]));
});
return imgLi;
}
var imageColorMode = Wrap(
children: formImgsColorBlendMode(),
);
如果以后有什么需要类比的模式,枚举什么的,都可以通过这种方式批量生成,效果又好又省事。
4. 对齐属性:alignment
有9个静态常量,分别是九个方位,另外也可以通过Alignment的构造方法来进行对齐偏移
var alignments = [
Alignment.center, Alignment.centerLeft, Alignment.centerRight,
Alignment.topCenter,Alignment.topLeft, Alignment.topRight,
Alignment.bottomCenter,Alignment.bottomLeft,Alignment.bottomRight,
Alignment(0.01,0.01),Alignment(0.5,0.5)
];
//循环生成Image控件
formImgAlignments() {
var imgLi = <Widget>[];
alignments.forEach((align) {
var img = Container(
margin: EdgeInsets.all(7),
width: 150,
height: 60,
color: randomRGB(),
child: Image(
image: AssetImage("images/wy_300x200_little.jpg"),
alignment: align,
));
imgLi.add(Column(
children: <Widget>[img, Text(e.toString())],
));
});
return imgLi;
}
var imageAlignments = Wrap(
children: formImgAlignments(),
);
2.5.重复模式:repeat
一目了然,不多说
var repeats = [
ImageRepeat.repeatY, ImageRepeat.repeatX,
ImageRepeat.noRepeat,ImageRepeat.repeat
];
//循环生成Image控件
formImgRepeat() {
var imgLi = <Widget>[];
repeats.forEach((repeat) {
var img = Container(
margin: EdgeInsets.all(7),
width: 150,
height: 90,
color: randomRGB(),
child: Image(
image: AssetImage("images/wy_300x200_little.jpg"),
repeat: repeat,
));
imgLi.add(Column(
children: <Widget>[img, Text(repeat.toString())],
));
});
return imgLi;
}
var imageRepeats = Wrap(
children: formImgRepeat(),
);
1.5:缩放质量:filterQuality
源码上说: 使用
FilterQuality.low
在缩放图片时使用二次线性插值算法FilterQuality.none
在缩放图片时使用临近算法FilterQuality.hight
是最好的,也是最慢的,通常是三次插值或更好FilterQuality.medium
的速度介于low和hight之间,通常是二次线性插值和锥体参数预滤波(mipmaps)的结合。
讲得挺高大上,但用起来感觉也就那回事,hight确实要比none感觉好
var qualitys = [
FilterQuality.none,FilterQuality.high,
FilterQuality.medium, FilterQuality.low,
];
//循环生成Image控件
formImgQualitys() {
var imgLi = <Widget>[];
qualitys.forEach((q) {
var img = Container(
margin: EdgeInsets.all(7),
width:110.0*3/2,
height: 110,
color: randomRGB(),
child: Image(
image: AssetImage("images/wy_300x200.jpg"),
filterQuality: q,
));
imgLi.add(Column(
children: <Widget>[img, Text(q.toString())],
));
});
return imgLi;
}
var imageQualitys = Wrap(
children: formImgQualitys(),
);
3.每日一布局:海贼王悬赏令
暂时没有抽成自定义组件。这里不分析了,有兴趣的小伙伴自己看看,也可以自定义个组件玩玩。
const double viewRate = 0.663306; //视图宽高比
const double imgRate = 1.234411;//图片宽高比
var width =300.0;
double height = width/viewRate;
var textWanted= Text('WANTED',
style: TextStyle(
fontWeight: FontWeight.bold,
letterSpacing:width/30,
fontSize: width/6),
);
var name =Text('NA MI',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: width/9),
);
var price= Text('16,000,000',
style: TextStyle(
letterSpacing:width/45,
fontWeight: FontWeight.bold,
fontSize: width/10),
);
var img =Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.black,width: width/100),
),
width: width,
height: width/imgRate,
child: Image.asset('images/娜美.jpg',fit: BoxFit.cover,),
);
var bottom =Stack(
children: <Widget>[
Image.asset('images/bottom.jpg',fit: BoxFit.fitWidth,),
Container(child: name,alignment: Alignment.topCenter,padding: EdgeInsets.only(top: 6*width/100),),
Container(child: price,alignment: Alignment.topCenter,padding: EdgeInsets.only(top: 17*width/100),)
],);
var wanted = Container(
width: width,
height: height,
color: Color(0xffded0b5),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[textWanted,Padding(padding:
EdgeInsets.fromLTRB(5*width/100,0,5*width/100,5*width/100),child: img,),
bottom
],),
);
var result=Card(child:wanted ,elevation: 5*width/100,);//最终组件