Flutter 127: 图解基础 Image 小组件

简介: 0 基础学习 Flutter,第一百二十七步:进一步了解学习基础 Image Widget!

    Image 图片作为日常中最常用的 Widget 却也是最容易忽略的,小菜在日常中通常仅用到 Image 展示图片属性,但是 Image 本身非常强大,有很多小菜所不熟知的属性特征;今天小菜重新认识一下 Image Widget

Image

    Image 作为支持展示多种图片格式的 Widget,提供了多种构造方法;

  • Image() 用于从 ImageProvider 中获取图片资源;
  • Image.asset() 用于从 AssetBundle 中获取工程目录图片资源;
  • Image.network() 用于从 URL 中获取网络图片资源;
  • Image.file() 用于从 File 中获取本地图片资源;
  • Image.memory() 用于从 Uint8List 中获取内存图片资源;

源码分析

const Image({
    Key key,
    @required this.image,       // 图片资源
    this.frameBuilder,          // 帧构造器
    this.loadingBuilder,        // 加载过程帧构造器
    this.errorBuilder,          // 失败状态帧构造器
    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.isAntiAlias = false,
    this.filterQuality = FilterQuality.low,
})

    简单分析源码可得,Image 作为一个有状态的 StatefulWidget,主要通过 image 属性来设置图片资源,多种附加属性来支持图片更多样的展示效果;小菜逐一进行尝试学习;

案例尝试

1. image

    Image 通过 ImageProvider 来展示图片,Flutter 提供了多种方式,与各类命名构造方法对应;

_imageWid00(isNet) => Image(
    image: isNet
        ? NetworkImage('https://flutter.github.io/assets-for-api-docs/assets/widgets/owl.jpg')
        : AssetImage('images/icon_hzw01.jpg'));

2. frameBuilder

typedef ImageFrameBuilder = Widget Function(
  BuildContext context,
  Widget child,
  int frame,
  bool wasSynchronouslyLoaded,
);

    frameBuilder 帧构造器用于控制在 Image 构建时小部件签名,其中 child 用于保存默认 Image 图片并且不可为空;frame 为渲染 Image 帧数下标,默认为首帧;可以通过 frameBuilder 设置图片基本样式;

_imageWid01(isNet) {
  return Image(
      frameBuilder: (BuildContext context, Widget child, int frame, bool wasSynchronouslyLoaded) {
        return Container(
            padding: EdgeInsets.all(18.0),
            color: Colors.deepOrange.withOpacity(0.4),
            child: child);
      },
      image: isNet
          ? NetworkImage('https://flutter.github.io/assets-for-api-docs/assets/widgets/owl.jpg')
          : AssetImage('images/icon_hzw01.jpg'));
}

3. loadingBuilder

    loadingBuilder 加载状态帧构造器,在加载过程中展示的 Image 构造器;查看效果图可以看到,设置了两层内边距,因为在 loading 状态和加载完状态时都对 child 设置了内边距;

_imageWid02(isNet) {
  return Image(
      frameBuilder: (BuildContext context, Widget child, int frame, bool wasSynchronouslyLoaded) {
        return Container(
            padding: EdgeInsets.all(18.0),
            color: Colors.deepOrange.withOpacity(0.4),
            child: child);
      },
      loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent loadingProgress) {
        return Container(
            padding: EdgeInsets.all(18.0),
            color: Colors.green.withOpacity(0.4),
            child: child);
      },
      image: isNet
          ? NetworkImage('https://flutter.github.io/assets-for-api-docs/assets/widgets/owl.jpg')
          : AssetImage('images/icon_hzw01.jpg'));
}

4. errorBuilder

    errorBuilder 为失败时替换 Image 展示的构造器;

_imageWid03(isNet) {
  return Image(
      frameBuilder: (BuildContext context, Widget child, int frame, bool wasSynchronouslyLoaded) {
        return Container(
            padding: EdgeInsets.all(18.0),
            color: Colors.deepOrange.withOpacity(0.4),
            child: child);
      },
      loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent loadingProgress) {
        return Container(
            padding: EdgeInsets.all(18.0),
            color: Colors.green.withOpacity(0.4),
            child: child);
      },
      errorBuilder: (BuildContext context, Object exception, StackTrace stackTrace) {
        return Container(
            height: 100.0, padding: EdgeInsets.all(18.0),
            color: Colors.grey.withOpacity(0.4),
            child: Center(child: Icon(Icons.error)));
      },
      image: isNet
          ? NetworkImage('https://flutter.github.io/assets-for-api-docs/assets/widgets/owl11.jpg')
          : AssetImage('images/icon_hzw0111.jpg'));
}

5. width & height

    width & height 为设置图片展示宽高尺寸;

_imageWid05(width, height) => Image(image: AssetImage('images/icon_hzw01.jpg'), width: width, height: height);

6. color & colorBlendMode

    color & colorBlendMode 配合使用绘制的混合模式,可以用来创建其他效果,如黑白模式,X 光特效等;之前小菜有所尝试;

_imageWid06(isNet, index) {
  BlendMode blendMode;
  if (index == 0) {
    blendMode = BlendMode.difference;
  } else if (index == 1) {
    blendMode = BlendMode.screen;
  } else if (index == 2) {
    blendMode = BlendMode.hardLight;
  } else {
    blendMode = BlendMode.colorBurn;
  }
  return Image(
      color: Colors.indigoAccent.withOpacity(0.4),
      colorBlendMode: blendMode,
      image: isNet
          ? NetworkImage('https://flutter.github.io/assets-for-api-docs/assets/widgets/owl.jpg')
          : AssetImage('images/icon_hzw01.jpg'));
}

7. alignment

    alignment 为边界内的对齐方式;当图片资源小于图片尺寸时,可以通过 Alignment 调整对齐方式;

_imageWid07(index) {
  Alignment alignment;
  if (index == 0) {
    alignment = Alignment.topLeft;
  } else if (index == 1) {
    alignment = Alignment.center;
  } else {
    alignment = Alignment.bottomRight;
  }
  return Image(
      image: AssetImage('images/icon_wechat_moments.png'),
      alignment: alignment,
      height: 120,
      frameBuilder: (BuildContext context, Widget child, int frame, bool wasSynchronouslyLoaded) {
        return Container(
            padding: EdgeInsets.all(2.0),
            color: Colors.deepOrange.withOpacity(0.4),
            child: child);
      });
}

8. repeat

    repeat 为覆盖图片未覆盖区域样式,包括水平方向或竖直方向平铺效果;

_imageWid08(index) {
  ImageRepeat repeat;
  if (index == 0) {
    repeat = ImageRepeat.repeatX;
  } else if (index == 1) {
    repeat = ImageRepeat.repeatY;
  } else {
    repeat = ImageRepeat.repeat;
  }
  return Image(
      image: AssetImage('images/icon_wechat_moments.png'),
      repeat: repeat, height: 120,
      frameBuilder: (BuildContext context, Widget child, int frame, bool wasSynchronouslyLoaded) {
        return Container(
            padding: EdgeInsets.all(18.0),
            color: Colors.deepOrange.withOpacity(0.4),
            child: child);
      });
}

9. fit

    fit 为图片在布局中的分布效果;

  • BoxFit.fitWidth:整体图片资源以图片宽度为基准放大或缩小;
  • BoxFit.fitHeight:整体图片资源以图片高度为基准放大或缩小;
  • BoxFit.fill:整体图片填充满图片宽高,可进行拉伸或压缩等;
  • BoxFit.contain:整体图片按比例放大或缩小至最大宽或高可容纳范围,并在设置宽高内居中整体显示;
  • BoxFit.cover:整体图片按比例放大或缩小至最小宽或高可容纳范围,并居中显示;
  • BoxFit.scaleDown:整体图片大于设置尺寸,按比例缩小并居中显示;若整体图片小于设置尺寸,则不做处理,居中显示;
_imageWid09(index) {
  BoxFit fit;
  if (index == 0) {
    fit = BoxFit.fitWidth;
  } else if (index == 1) {
    fit = BoxFit.fitHeight;
  } else if (index == 2) {
    fit = BoxFit.fill;
  } else if (index == 3) {
    fit = BoxFit.cover;
  } else if (index == 4) {
    fit = BoxFit.contain;
  } else {
    fit = BoxFit.scaleDown;
  }
  return Image(
      image: AssetImage('images/icon_hzw03.jpg'),
      fit: fit, height: 120,
      frameBuilder: (BuildContext context, Widget child, int frame, bool wasSynchronouslyLoaded) {
        return Container(
            padding: EdgeInsets.all(2.0),
            color: Colors.deepOrange.withOpacity(0.4),
            child: child);
      });
}

10. centerSlice

    centerSlice 用于设置一个矩形,类似于 .9.png 图一样,进行固定范围的拉伸;其中注意 fit 类型不可为 BoxFit.noneBoxFit.cover

_imageWid10(index) {
  Rect rect;
  if (index == 0) {
    rect = null;
  } else if (index == 1) {
    rect = Rect.fromLTWH(100, 100, 50, 50);
  } else if (index == 2) {
    rect = Rect.fromLTWH(50, 50, 50, 50);
  }
  return Image(
      fit: BoxFit.contain,
      width: 250,
      height: 250,
      centerSlice: rect,
      image: AssetImage('images/icon_music.png'));
}


    Image 案例源码


    小菜对 Image 的学习还仅限于基础应用,对于平时不常用的属性有了进一步了解,但对源码的学习还不够深入;如有错误,请多多指导!

来源: 阿策小和尚
目录
相关文章
|
12天前
Flutter 组件(二)文本 与 输入框组件
Flutter 组件(二)文本 与 输入框组件
89 0
|
12天前
|
容器
Flutter 组件(一)组件概述
Flutter 组件(一)组件概述
63 0
|
11天前
|
设计模式 JavaScript 前端开发
flutter组件封装技巧
工厂函数不会自动调用,需要手动调用
18 3
|
12天前
|
前端开发 搜索推荐 UED
【Flutter前端技术开发专栏】Flutter中的高级UI组件应用
【4月更文挑战第30天】探索Flutter的高级UI组件,如`TabBar`、`Drawer`、`BottomSheet`,提升应用体验和美观度。使用高级组件能节省开发时间,提供内置交互逻辑和优秀视觉效果。示例代码展示了如何实现底部导航栏、侧边导航和底部弹出菜单。同时,自定义组件允许个性化设计和功能扩展,但也带来性能优化和维护挑战。参考Flutter官方文档和教程,深入学习并有效利用这些组件。
【Flutter前端技术开发专栏】Flutter中的高级UI组件应用
|
12天前
|
Dart 前端开发 开发者
【Flutter前端技术开发专栏】Flutter Dart语言基础语法解析
【4月更文挑战第30天】Dart是Google为Flutter框架打造的高效编程语言,具有易学性、接口、混入、抽象类等特性。本文概述了Dart的基础语法,包括静态类型(如int、String)、控制流程(条件、循环)、函数、面向对象(类与对象)和异常处理。此外,还介绍了库导入与模块使用,帮助开发者快速入门Flutter开发。通过学习Dart,开发者能创建高性能的应用。
【Flutter前端技术开发专栏】Flutter Dart语言基础语法解析
|
12天前
|
Dart
Flutter 中优雅切换应用主题的组件
【Flutter】使用adaptive_theme组件优雅切换应用主题:封装MaterialApp,支持light/dark/system模式,自定义色彩,保存选择,含调试按钮。安装配置、设置主题、监听切换、自定义颜色、读取配置步骤详细。代码示例与学习路径推荐。[查看完整教程](https://flutter.ducafecat.com/blog/flutter-app-theme-switch)
Flutter 中优雅切换应用主题的组件
|
8月前
|
人机交互
Flutter笔记 - ListTile组件及其应用
Flutter笔记 - ListTile组件及其应用
110 0
|
12天前
|
开发者 索引 容器
Flutter开发笔记:Flutter 布局相关组件
Flutter开发笔记:Flutter 布局相关组件
144 0
|
12天前
|
iOS开发
Flutter 组件(三)按钮类组件
Flutter 组件(三)按钮类组件
172 0
|
10月前
|
缓存 Dart 前端开发
Flutter 中使用 Widgetbook 管理你的组件 | 猫哥
Flutter 界面开发中我们有几个痛点 : - 与设计师协作复用一套设计规范(figma) - 可视化的管理你的组件代码(基础组件、业务组件) - 不同设备尺寸测试你的组件 - 实时修改你的测试组件参数
4221 1
Flutter 中使用 Widgetbook 管理你的组件 | 猫哥