Flutter Widget:实例讲解图片组件Image、Icon、ImageIcon


前言

  • Flutter 作为Google出品的一个新兴的跨平台移动客户端UI开发框架,正在被越来越多的开发者和组织使用,包括阿里的咸鱼、腾讯的微信等。

    示意图

  • 今天,我主要讲解Flutter中图片组件方面的Widget,包括Image、Icon、ImageIcon,希望你们会喜欢。

示意图

1. Image

1.1 作用

显示图片,主要支持的加载方式:本地图片、资源图片 & 网络图片。

1.2 常用属性

const Image({
    Key key,
    @required this.image,// ImageProvider,必填参数,接收一个ImageProvider 类型的值
    this.semanticLabel, // String,图片的描述
    this.excludeFromSemantics = false, // bool,是否从语义上排除该图片,默认值为false
    this.width, // double,图片的宽度
    this.height, // double,图片的高度
    this.color, // Color,图片的前景色,一般不设置或设置透明色,会覆盖掉图片,一般会和colorBlendMode结合使用
    this.colorBlendMode, // BlendMode,一般和color结合使用,设置color的混合模式
    this.fit, // BoxFit,设置图片的显示模式
    this.alignment = Alignment.center, // AlignmentGeometry,用于设置图片的对齐方式,默认值:Alignment.center
    this.repeat = ImageRepeat.noRepeat, // ImageRepeat,图片的重复方式,当图片没有完全覆盖掉容器时使用。默认值:ImageRepeat.noRepeat
    ...
  })

下面,将详细讲解Image的属性。

1.3 属性image

  • 接收一个ImageProvider类型的值。ImageProvider是一个抽象类
  • 实现类主要包括:AssetImage、MemoryImage、NetworkImage、FileImage,分别表示可从资源、内存、网络 & 文件中获取图片
// 加载网络图片
Image.network(String src, {
    Key key,
    double scale = 1.0,
    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,
    Map<String, String> headers,
  })

// 加载本地文件
  Image.file(File file, {
    Key key,
    double scale = 1.0,
    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,
  })

// 从项目资源中加载
Image.asset(String name, {
    Key key,
    AssetBundle bundle,
    this.semanticLabel,
    this.excludeFromSemantics = false,
    double scale,
    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,
    String package,
    this.filterQuality = FilterQuality.low,
  })

// 从内存中加载
 Image.memory(Uint8List bytes, {
    Key key,
    double scale = 1.0,
    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,
  })

为了方便使用,在Image的构造方法里也加入了快速从各种不同途径获得图片的方式,Image的构造方法包括:

Image()  // 通用方法,使用ImageProvider实现,如下方法本质上也是使用的这个方法
Image.asset // 加载资源图片
Image.file  // 加载本地图片文件
Image.network  // 加载网络图片
Image.memory   // 加载Uint8List资源图片
// 获得资源图片
new Image.asset('imgs/logo.jpeg')

// 获得网络图片
new Image.network(
  'https://flutter.io/images/homepage/header-illustration.png')

// 获得本地文件图片
new Image.file(new File("/Users/gs/Downloads/1.jpeg"))

// 获得Uint8List图片
new Image.memory(bytes)

// 获得使用ImageProvider加载图片
new Image(image: new NetworkImage(
  "https://flutter.io/images/homepage/screenshot-2.png"),)

此处特别说明加载本地的资源图片

步骤1:创建一个文件夹存放图片

此处创建的是文件夹名 = assetImage,放了一个名为photo.jpg的图片

步骤2:在pubspec.yaml中声明资源

注:声明时路径和前面的- 存在间隔

步骤3:加载时填写正确资源路径

// 获得资源图片
new Image.asset('assetImage/photo.jpg')
  • 实际测试代码

main.dart

import 'package:flutter/material.dart';// Material UI组件库

void main() => runApp(MyApp());

// 无状态控件显示
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
// 主界面入口返回的组件 = MaterialApp
    return MaterialApp(
      title: 'Widget_Demo', //标题
      theme: ThemeData(primarySwatch: Colors.blue), //主题色
      home: MyHomePage(), // 返回一个Widget对象,用来定义当前应用打开的时候,所显示的界面
    );
  }
}

// 返回的Widget对象
class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      //设置appbar
      appBar: new AppBar(
        title: new Text('Flutter Demo'),
      ),
      //主体
      body: new Image.asset('assetImage/photo.jpg')
    );
  }

}
  • 测试效果

1.4 属性width & height、fit

  • 属性说明
// 代表Image显示区域的宽度和高度设置
this.width, // double,图片的宽度
this.height, // double,图片的高度

this.fit, // BoxFit,设置图片的显示模式,具体设置如下图

// 此处将两个属性一起说明是因为:
// 图片的容器Image Widget的宽高 & 图片本身的大小不一样(需区分开来)
// 所以结合图片的显示模式讲解
  • 使用
    main.dart
void main() => runApp(MyApp());

// 无状态控件显示
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
// 主界面入口返回的组件 = MaterialApp
    return MaterialApp(
      title: 'Widget_Demo', //标题
      theme: ThemeData(primarySwatch: Colors.blue), //主题色
      home: MyHomePage(), // 返回一个Widget对象,用来定义当前应用打开的时候,所显示的界面
    );
  }
}

// 返回的Widget对象
class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        //设置appbar
        appBar: new AppBar(
          title: new Text('Flutter Demo'),
        ),
        //主体
        body: new Image.asset(
          'assetImage/photo.jpg',
          width: 200.0,
          height: 100.0,
          fit: BoxFit.fill,
        ));
  }
}

1.5 属性color、colorBlendMode

  • 属性说明
this.color
// Color,图片的前景色,一般不设置或设置透明色,会覆盖掉图片,一般会和colorBlendMode结合使用

this.colorBlendMode
// BlendMode,一般和color结合使用,设置color的混合模式,具体设置属性如下:
  • 使用
    main.dart
import 'package:flutter/material.dart';// Material UI组件库

void main() => runApp(MyApp());

// 无状态控件显示
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
// 主界面入口返回的组件 = MaterialApp
    return MaterialApp(
      title: 'Widget_Demo', //标题
      theme: ThemeData(primarySwatch: Colors.blue), //主题色
      home: MyHomePage(), // 返回一个Widget对象,用来定义当前应用打开的时候,所显示的界面
    );
  }
}

// 返回的Widget对象
class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      //设置appbar
      appBar: new AppBar(
        title: new Text('Flutter Demo'),
      ),
      //主体
        body: new Image.asset(
          'assetImage/photo.jpg',
          width: 200.0,
          height: 100.0,
          fit: BoxFit.fill,
          color: Colors.red,
          colorBlendMode: BlendMode.colorDodge,
        ));
  }
}
  • 测试效果


1.6 属性alignment

  • 属性说明
this.alignment = Alignment.center
// AlignmentGeometry,用于设置图片的对齐方式,默认值:Alignment.center,可设置的属性如下:
  • 具体使用
    为了方便展示,此处加入一个布局容器Container方便展示。

main.dart

import 'package:flutter/material.dart';// Material UI组件库

void main() => runApp(MyApp());

// 无状态控件显示
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
// 主界面入口返回的组件 = MaterialApp
    return MaterialApp(
      title: 'Widget_Demo', //标题
      theme: ThemeData(primarySwatch: Colors.blue), //主题色
      home: MyHomePage(), // 返回一个Widget对象,用来定义当前应用打开的时候,所显示的界面
    );
  }
}

// 返回的Widget对象
class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      //设置appbar
      appBar: new AppBar(
        title: new Text('Flutter Demo'),
      ),
        // 主体
        body: Container(
          width: 500,
          height: 1000,
          color: Colors.red,
          child: Image.asset(
            'assetImage/photo.jpg',
            width: 50.0,
            height: 50.0,
            alignment: Alignment.bottomCenter,
            fit: BoxFit.contain,
          ),
        ));
  }
}
  • 测试效果

1.7 属性Repeat

  • 属性说明
this.repeat = ImageRepeat.noRepeat
// ImageRepeat,图片的重复方式,当图片没有完全覆盖掉容器时使用。默认值:ImageRepeat.noRepeat

// 枚举类型
repeat // 1. 在x轴和y轴重复
repeatX // 2. 在x轴重复
repeatY // 3. 在y轴重复
noRepeat // 4. 不重复
  • 具体使用
import 'package:flutter/material.dart';// Material UI组件库

void main() => runApp(MyApp());

// 无状态控件显示
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
// 主界面入口返回的组件 = MaterialApp
    return MaterialApp(
      title: 'Widget_Demo', //标题
      theme: ThemeData(primarySwatch: Colors.blue), //主题色
      home: MyHomePage(), // 返回一个Widget对象,用来定义当前应用打开的时候,所显示的界面
    );
  }
}

// 返回的Widget对象
class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      //设置appbar
      appBar: new AppBar(
        title: new Text('Flutter Demo'),
      ),
        //主体
        body: Container(
          width: 500,
          height: 1000,
          color: Colors.red,
          child: Image.asset(
            'assetImage/photo.jpg',
            width: 50.0,
            height: 50.0,
            alignment: Alignment.bottomCenter,
            fit: BoxFit.contain,
            repeat: ImageRepeat.noRepeat,
          ),
        ));
  }
}
  • 测试效果

至此,关于Image Widget讲解完毕。


2. Icon

2.1 作用

显示图标图片

2.2 优势(相对于Image)

  • 体积小:可以减小安装包大小。
  • 矢量:矢量图标,放大不会影响其清晰度。
  • 可应用文本样式:可以像文本一样改变字体图标的颜色、大小对齐等 & 可通过TextSpan和文本混用

2.3 构造方法

 const Icon(this.icon, {
    Key key, // 设置使用的图标
    this.size, // 图标大小
    this.color, // 颜色
    this.textDirection, // 渲染图标的文本方向
  })

2.4 具体使用

void main() => runApp(MyApp());

// 无状态控件显示
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
// 主界面入口返回的组件 = MaterialApp
    return MaterialApp(
      title: 'Widget_Demo', //标题
      theme: ThemeData(primarySwatch: Colors.blue), //主题色
      home: MyHomePage(), // 返回一个Widget对象,用来定义当前应用打开的时候,所显示的界面
    );
  }
}

// 返回的Widget对象
class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      //设置appbar
      appBar: new AppBar(
        title: new Text('Flutter Demo'),
      ),
        //主体
        body: Icon(
          Icons.camera,
          size: 50,
          color: Colors.red,
          textDirection: TextDirection.ltr,
        ));
  }
}

2.5 测试效果

2.6 特别说明

Flutter默认包含了一套Material Design的字体图标,在pubspec.yaml文件中的配置如下



3. ImageIcon

3.1 作用

自定义图形图标,来自于图片绘制。图标不可交互式。

3.2 构造函数

  const ImageIcon(this.image, {
    Key key, 
    this.size, // 图标大小
    this.color, // 颜色
  })
  • 区别于Icon,ImageIcon是采用自定义ImageProvider来定义图标
  • 自定义ImageProvider分别是上面讲解Image的:AssetImage、MemoryImage、NetworkImage、FileImage,即分别表示可从资源、内存、网络 & 文件中获取图片
// 加载网络图片
Image.network(String src, {
    Key key,
    double scale = 1.0,
    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,
    Map<String, String> headers,
  })

// 加载本地文件
  Image.file(File file, {
    Key key,
    double scale = 1.0,
    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,
  })

// 从项目资源中加载
Image.asset(String name, {
    Key key,
    AssetBundle bundle,
    this.semanticLabel,
    this.excludeFromSemantics = false,
    double scale,
    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,
    String package,
    this.filterQuality = FilterQuality.low,
  })

// 从内存中加载
 Image.memory(Uint8List bytes, {
    Key key,
    double scale = 1.0,
    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,
  })

// 为了方便使用,在Image的构造方法里也加入了快速从各种不同途径获得图片的方式,Image的构造方法包括:
Image()  // 通用方法,使用ImageProvider实现,如下方法本质上也是使用的这个方法
Image.asset // 加载资源图片
Image.file  // 加载本地图片文件
Image.network  // 加载网络图片
Image.memory   // 加载Uint8List资源图片

3.3 具体使用

import 'package:flutter/material.dart';// Material UI组件库

void main() => runApp(MyApp());

// 无状态控件显示
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
// 主界面入口返回的组件 = MaterialApp
    return MaterialApp(
      title: 'Widget_Demo', //标题
      theme: ThemeData(primarySwatch: Colors.blue), //主题色
      home: MyHomePage(), // 返回一个Widget对象,用来定义当前应用打开的时候,所显示的界面
    );
  }
}

// 返回的Widget对象
class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      //设置appbar
        appBar: new AppBar(
          title: new Text('Flutter Demo'),
        ),
        //主体
        body: ImageIcon(AssetImage(
            'assetImage/plane.png'), // 注:此处的图片格式必须是.png哦!!
          size: 300,
          color: Colors.red,)
    );
  }
}

3.4 测试效果图

至此,关于图片方面的Widget讲解完毕。


4. 总结

  • 本文主要讲解了Flutter中图片组件方面的Widget,包括Image、Icon、ImageIcon
  • 接下来推出的文章,我将继续讲解Flutter的相关知识,包括更多的Widget用法、实例应用等,感兴趣的读者可以继续关注我的博客哦:Carson_Ho的Android博客

请点赞!因为你们的赞同/鼓励是我写作的最大动力!

相关文章阅读
Android开发:最全面、最易懂的Android屏幕适配解决方案
Android开发:史上最全的Android消息推送解决方案
Android开发:最全面、最易懂的Webview详解
Android开发:JSON简介及最全面解析方法!
Android四大组件:Service服务史上最全面解析
Android四大组件:BroadcastReceiver史上最全面解析


欢迎关注Carson_Ho的简书!

不定期分享关于安卓开发的干货,追求短、平、快,但却不缺深度

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容