为了账号安全,请及时绑定邮箱和手机立即绑定

Flutter小课堂-Image篇

标签:
CSS3
前言

图片是一个我们又爱又恨的东西,它是万美之本,也是万恶之源
为阐述清楚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,);//最终组件
点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
移动开发工程师
手记
粉丝
21
获赞与收藏
57

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消