[Flutter]flutter基础之组件基础(三)

一、Image Widget

Image Widget 是 Flutter 中用来显示图片的小部件。支持以下图像格式:JPEG,PNG,GIF,动画GIF,WebP,动画WebP,BMP和WBMP 。 Image Widget 提供了以下构造函数用于创建图像:

Image() ,用于从 ImageProvider 获取图像。

Image.asset() ,从 AssetBundle 获取图像。

Image.network ,从URL获取图像。

Image.file ,从本地文件获取图像。

Image.memory ,从 Uint8List 获取图像。

1. Image() 构造方法
const Image({
  Key key,
  //ImageProvider类型必传参数,为要显示的图像
  @required this.image,
  //ImageFrameBuilder类型可选命名参数,是一个Function,返回一个代表该图像的Widget
  this.frameBuilder,
  //ImageLoadingBuilder类型可选命名参数,用于指定在图像加载过程中向用户展示的Widget
  this.loadingBuilder,
  //String类型可选命名参数,为图像的语义标签
  this.semanticLabel,
  //bool类型可选命名参数,是否从语义中排除此图像
  this.excludeFromSemantics = false,
  //double类型可选命名参数,图像要显示的宽度
  this.width,
  //double类型可选命名参数,图像要显示的高度
  this.height,
  //Color类型可选命名参数,如果不为null,则使用colorBlendMode将此颜色与每个图像像素混合
  this.color,
  //BlendMode类型可选命名参数,用于设置color与图像混合的模式
  this.colorBlendMode,
  //BoxFit类型可选命名参数,用于设置图像的填充模式
  this.fit,
  //AlignmentGeometry类型可选命名参数,设置图像的对齐模式,其为抽象类,使用其子类Alignment
  this.alignment = Alignment.center,
  //ImageRepeat类型可选命名参数,用于设置布局中图像的重复模式
  this.repeat = ImageRepeat.noRepeat,
  //Rect类型可选命名参数,用于设置当一个图片被拉伸时的范围
  this.centerSlice,
  //bool类型可选命名参数,用于设置是否以TextDirection相同的方向来绘制图像
  this.matchTextDirection = false,
  //bool类型可选命名参数,用于设置在图像提供者更改时,是否继续显示旧图像。
  //true为显示旧图像,false为暂时不显示任何图像
  this.gaplessPlayback = false,
  //FilterQuality类型可选命名参数,用于设置图片的过滤质量
  this.filterQuality = FilterQuality.low,
})

Image() 构造方法的必传参数类型为 ImageProvider ,是一个抽象类,不能直接实例化。其有5个直接子类分别为:AssetBundleImageProviderFileImageMemoryImageNetworkImageResizeImage ,可以直接使用。这几个类,是根据不同的图片源选择对应的加载方式,使用方式如下:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("Widget基础"),
        ),
        body: studyWidget(context),
      ),
    );
  }
}

//示例代码只修改此函数
Widget studyWidget(BuildContext context) {
  return Image(
    image: NetworkImage("http://www.mwpush.com/uploads/avatar.png"),
  );
}
2. Image.network() 构造方法
Image.network(
  //String类型必传参数,用于设置图片的网络URL地址
  String src, {
  Key key,
  //double类型可选命名参数,图像的缩放级别,值越大图片越小
  double scale = 1.0,
  this.frameBuilder,
  this.loadingBuilder,
  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类型可选命名参数,用于发送带有图像请求的自定义的HTTP头  
  Map headers,
  //int类型可选命名参数,用于减少ImageCache的内存使用量
  int cacheWidth,
  //int类型可选命名参数,用于减少ImageCache的内存使用量  
  int cacheHeight,
}) 
//以上未注释的参数与Image()构造方法含义相同  

本构造方法是当从网络加载图片时使用,使用方式如下:

Widget studyWidget(BuildContext context) {
  return Image.network("http://www.mwpush.com/uploads/avatar.png");
}

在创建 Image Widget 时,最好指定其大小,或者放在能严格限制其布局的上下文中,否则图像尺寸会随时图像的加载而改变。

Widget studyWidget(BuildContext context) {
  return Image.network(
    "http://www.mwpush.com/uploads/avatar.png",
    width: 200,
    height: 200,
  );
}

效果如下:


202035639.jpg

一般一个 Image Widget 都是放在特定的 Widget 中的,这样可以限制其展示范围,也可以有良好的布局。其很多属性也依赖于外围 Widget。这里使用 Container Widget ,如下:

Widget studyWidget(BuildContext context) {
  return Container(
    width: 400,
    height: 200,
    color: Colors.yellow,
    child: Image.network(
      "http://www.mwpush.com/uploads/avatar.png",
      width: 100,
      height: 400,
    ),
  );
}

效果如下:

202035649.jpg

从上图可以发现,当 Image Widget 放在一个布局组件中以后,其 widthheight 属性就不起作用了,其在保持原图比例的情况下会尽量占满其父级 Widget ,且位于中间显示。我们可以设置其填充属性做更改,如下:

Widget studyWidget(BuildContext context) {
  return Container(
    width: 400,
    height: 200,
    color: Colors.yellow,
    child: Image.network(
      "http://www.mwpush.com/uploads/avatar.png",
      fit: BoxFit.fill,
    ),
  );
}

BoxFit 是一个枚举类型,如下:

enum BoxFit {
    /// 完全填充目标容器,如目标容器比例与图比例不同,图会被拉伸
  /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_fill.png)
  fill,
    /// 尽可能大的展示完整图片并且会保持原图比例,所以对于矩形来说,总会有对应的面被对齐容器边缘,上下、左右
  /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_contain.png)
  contain,
  /// 保持原图比例的情况下尽可能小的展示图片,但是会在覆盖整个容器的情况下尽可能小
  /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_cover.png)
  cover,
  /// 保持原图比例的情况下填充目标容器宽度,上下如果溢出会被裁掉
  /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_fitWidth.png)
  fitWidth,
  /// 保持原图比例的情况下填充目标容器高度,左右如果溢出会被裁掉
  /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_fitHeight.png)
  fitHeight,
  /// 在目标荣内展示原图,不对宽高做更改。以原图的大小居中显示,溢出部分被裁掉
  /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_none.png)
  none,
  /// 在目标容器居中对齐原图。如果需要,将源文件向下缩放,以确保源文件适合该框
  /// ![](https://flutter.github.io/assets-for-api-docs/assets/painting/box_fit_scaleDown.png)
  scaleDown,
}

上面对应的都有官方的样式图片地址,可自行查看。

图像的对齐模式是相对于父级容器来说的,实现如下:

Widget studyWidget(BuildContext context) {
  return Container(
    width: 400,
    height: 600,
    color: Colors.yellow,
    child: Image.network(
      "http://www.mwpush.com/uploads/avatar.png",
      alignment: Alignment.centerRight,  //中心靠右对齐
    ),
  );
}

效果如下图:

202035836.jpg

也可以设置其他对齐方式,可自行查看,都比较简单,选择对应的选项就可以。

图像的重复模式,就是当一个图像并不能完全占满父级容器时,以什么样的模式进行填充, 如下:

Widget studyWidget(BuildContext context) {
  return Container(
    width: 400,
    height: 600,
    color: Colors.yellow,
    child: Image.network(
      "http://www.mwpush.com/uploads/avatar.png",
      repeat: ImageRepeat.repeatY,
    ),
  );
}

以上是按照Y轴重复的模式填充,效果如下:

202035846.jpg

也可以按照X轴填充,同时按照X,Y轴填充等。

填充颜色,其中的 color 属性,当单独设置颜色属性时,就是绘制图片的颜色,图片内容将被覆盖。可以选择颜色与原图的混合模式进行设置,如下:

Widget studyWidget(BuildContext context) {
  return Container(
    width: 400,
    height: 600,
    color: Colors.yellow,
    child: Image.network(
      "http://www.mwpush.com/uploads/avatar.png",
      color: Colors.red,   //设置源颜色
      colorBlendMode: BlendMode.difference,   //设置混合模式
    ),
  );

效果如下:

202035922.jpg

更多混合效果及方法,官网查看地址:https://api.flutter.dev/flutter/dart-ui/BlendMode-class.html

对于图片拉伸属性 centerSlice ,其值为一个 Rect ,我们通过一张图片的设置来说明这个参数的设置。这里准备了一张原图,如下:

centerSlice.jpg

这张图被分割线分成了9个矩形,centerSlice 设置的矩形区域为标记为5的矩形区域。这里的图片宽度为1000 ,高度为500 ,区域 1,3,7,9 的宽高均为100 ,所以可以得出区域 5 的左上角的起始坐标为100,100,宽度为800 ,高度为 300 。 这里使用了加载本地 AssetBundle 的文件方式加载的图片,下面会进行讲解。这里先展示原图的代码,代码如下:

Widget studyWidget(BuildContext context) {
  return Container(
    width: 400,
    height: 600,
    color: Colors.yellow,
    child: Image.asset(
      "images/centerSlice.jpg",
      scale: 3,
    ),
  );
}

效果如下:

2020351025.jpg

由于图片太大,为了在 Container 边缘留有空间,使用了缩放属性 scale

设置拉伸属性代码如下:

Widget studyWidget(BuildContext context) {
  return Container(
    width: 400,
    height: 600,
    color: Colors.yellow,
    child: Image.asset(
      "images/centerSlice.jpg",
      scale: 3,
      centerSlice: Rect.fromLTWH(100, 100, 800, 300),
    ),
  );
}

效果如下:

2020351027.jpg

这里我们使用了 Rect.fromLTWH() 构造方法创建 Rect 。其参数依次分别为距离左侧的距离,距离顶部的距离,宽度,高度。通过前两个属性,我们可以得知,在本图中,L和T属性能确定矩形的起始点就是图中区域 1 的 右下角,跨度高度分别为上面计算的800和300,所以可以看出,除了区域 1,3,7,9 外,都会被拉伸。区域 2 和 区域 8 是横向拉伸,区域 4 和 区域 6 是纵向拉伸,区域 5 是横向纵向都拉伸。

3. Image.file() 构造方法
Image.file(
  //File类型必传参数,从File获取ImageStream
  File file, {
  Key key,
  double scale = 1.0,
  this.frameBuilder,
  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,
  int cacheWidth,
  int cacheHeight,
})
//以上未注释的参数与Image()构造方法含义相同   

Image.file() 是加载本地文件时使用,必传为 File 类型,使用 File 需要引入 dart:io 。使用方式如下:

Widget studyWidget(BuildContext context) {
  return Container(
    width: 400,
    height: 600,
    color: Colors.yellow,
    child: Image.file(
      File("/path/images/avatar.png"),   //path 为您的图片本地路径
    ),
  );
}
4. Image.asset() 构造方法
Image.asset(
  //String类型必传参数,从
  String name, {
  Key key,
  AssetBundle bundle,
  this.frameBuilder,
  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,
  int cacheWidth,
  int cacheHeight,
})
//以上未注释的参数与Image()构造方法含义相同   

Image.asset() 用来加载应用本身的资源图片。使用此方式时,需要在 pubspec.yaml 配置文件中对资源做配置。比如,在项目的根目录中新建 images 文件夹,并在其中添加图片 avatar.png ,需要在 pubspec.yaml 文件中有如下配置:

flutter:
  assets:
    - images/avatar.png

在默认创建的 pubspec.yaml 中有 assets 的配置示例,为被注释状态,在42行左右,进行修改即可。

使用方式如下:

Widget studyWidget(BuildContext context) {
  return Container(
    width: 400,
    height: 600,
    color: Colors.yellow,
    child: Image.asset(
      "images/avatar.png"
    ),
  );
}

在配置 pubspec.yaml 时,要注意 YAML 的语法规则,对齐方式很重要。

为了应对不同设备分辨率,可以同时配备一张图片的多张不同分辨率图片来对不同的显示做匹配。在 Flutter 中做如下处理。如提供2倍图与3倍图:

  1. 创建不同比例文件夹,在 images文件夹中新建名为 2x3x 的文件夹。其他比例同样操作。

  2. 将对应的2倍图放入 2x 文件,3倍图放入 3x 文件夹,同一图片的不同分辨率的图片名称格式要相同。如下图:

202036542.jpg
  1. pubspec.yaml 配置文件中配置如下:

    flutter:
      assets:
        - images/avatar.png
        - images/2x/avatar.png
        - images/3x/avatar.png
    
  2. 实现代码如下:

    Widget studyWidget(BuildContext context) {
      return Container(
        width: 400,
        height: 600,
        color: Colors.yellow,
        child: Image.asset(
          "images/avatar.png",
        ),
      );
    }
    

在像素比例为2.0的屏幕上,将自动加载渲染 images/2x/avatar.png 图片。可以不提供1倍图,但是 pubspec.yaml 中的配置 - images/avatar.png 必须存在,此时在需要1倍图的设备是上会使用2倍图代替。

5. Image.memory() 构造方法
Image.memory(
  //Uint8List类型必传参数,为图片的字节数组
  Uint8List bytes, {
  Key key,
  double scale = 1.0,
  this.frameBuilder,
  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,
  int cacheWidth,
  int cacheHeight,
})
//以上未注释的参数与Image()构造方法含义相同   

当通过网络或本地获取图片的字节数据进行图片渲染时,可以使用 Image.memory() 构造方法进行处理。如下:

import 'dart:typed_data';
import 'dart:convert';
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("Widget基础"),
        ),
        body: studyWidget(context),
      ),
    );
  }
}

Widget studyWidget(BuildContext context) {

  String imgString = "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";
  Uint8List bytes = base64.decode(imgString);
  return Container(
    width: 400,
    height: 600,
    color: Colors.yellow,
    child: Image.memory(
      bytes,
    ),
  );
}

二、Icon Widget

Icon 为一个图标 Widget ,是一个无状态组件,不可交互。Flutter 默认所有的 Icon Widget 都为正方形,如果使用其他形状可能会出错。 其构造函数如下:

const Icon(
  //IconData类型必传参数,为要显示的图标,可以为null,为null将显示指定大小的空白区域
  this.icon, {
  Key key,
  //double类型可选命名参数,绘制图标的大小,单位为像素
  this.size,
  //Color类型可选命名参数,绘制图标时使用的颜色,默认为黑色  
  this.color,
  //String类型可选命名参数,图标的语义标签  
  this.semanticLabel,
  //TextDirection类型可选命名参数,图标绘制的方向  
  this.textDirection,
})
1. 系统的 Icon

Flutter 为开发者提供了很多 Icon ,可以通过 Icons.图标名称 直接使用,方式如下:

Widget studyWidget(BuildContext context) {
  return Container(
    width: 400,
    height: 600,
    color: Colors.yellow,
    child: Icon(
      Icons.ac_unit,
      color: Colors.blue,
      size: 24.0,
    ),
  );
}

更多 Icon ,可以参考官方。 https://api.flutter.dev/flutter/material/Icons-class.html#constants

2. 自定义的 Icon

Icon 的构造函数中,必传参数 iconIconData 类型,其构造方法如下:

const IconData(
  //int类型必传参数,图标字体中存储该图标的Unicode代码点
  this.codePoint, {
  //String类型可命名选参数,字体名称  
  this.fontFamily,
  //String类型可选命名参数,包含字体的包的名称  
  this.fontPackage,
  //bool类型可选命名参数,图标绘制方法是否与环境中的文本绘制方向相同  
  this.matchTextDirection = false,
});

可以通过创建 IconData 的实例来自定义 Icon 。首先要准备素材,可以到阿里图标库下载,https://www.iconfont.cn/ 。这里随便下载一个为例。选择一个图标加入购物车,在购物车中选择下载代码。下载后内容如下图:

2020361109.jpg

在项目工程根目录新建 fonts 文件夹,并将 iconfont.ttf 文件加入到文件夹中,将文件重新命名为 my_shoes.ttf 。打开工程的 pubspec.yaml 配置文件,找到如下代码:

  # fonts:
  #   - family: Schyler
  #     fonts:
  #       - asset: fonts/Schyler-Regular.ttf
  #       - asset: fonts/Schyler-Italic.ttf
  #         style: italic
  #   - family: Trajan Pro
  #     fonts:
  #       - asset: fonts/TrajanPro.ttf
  #       - asset: fonts/TrajanPro_Bold.ttf
  #         weight: 700

修改如下:

  fonts:
     - family: MyCustomFont  
       fonts:
         - asset: fonts/my_shoes.ttf

关于 family 对应的名字可以自定义,如果有确定的不会与其他混淆可以直接使用提供的,如果内有可以自己定义字体名字,这里我们自定义为 MyCustomFont 。

然后打开下载的文件中的名字为 demo_index.html (使用浏览器打开即可)。如下图:

2020361135.jpg

&#x 是字符引用,后面接的是十六进制数字,我们要获取的就是&#x 后面的数字。

实现代码如下:

Widget studyWidget(BuildContext context) {

  const IconData iData = const IconData(
    0xe70c,
    fontFamily: "MyCustomFont",
  );

  return Container(
    width: 400,
    height: 600,
    color: Colors.yellow,
    child: Icon(
      iData,
      color: Colors.blue,
      size: 50.0,
    ),
  );
}

实现效果如下:

2020361139.jpg

你可能感兴趣的:([Flutter]flutter基础之组件基础(三))