Flutter速来系列6: Flutter的组件之Image,fit,混色,重复,例子足够多心里就有底了

2,338 阅读8分钟

一、Image组件

Image是Flutter中用于显示图像的组件,它可以加载网络图像、本地图像以及Asset中的图像资源。根据不同的用途和加载方式,Image可以分为以下几类:

二、分类

  1. NetworkImage: 用于加载网络图像。
  2. AssetImage: 用于加载Asset中的图像资源。
  3. FileImage: 用于加载本地文件系统中的图像文件。
  4. MemoryImage: 用于加载内存中的图像数据。

三 属性

下面是常用Image组件的属性列表及其描述:

image

image: 要显示的图像对象,可以是NetworkImage、AssetImage、FileImage或MemoryImage。


width

width: 图像的宽度。


height

height: 图像的高度。

alignment

alignment: 图像的对齐方式。


fit

fit: 图像的适应方式,用于调整图像在组件内的尺寸和比例。常用选项包括:

  • BoxFit.contain: 等比例缩放图像,使其完全显示在组件内,可能会有留白。
  • BoxFit.cover: 等比例缩放图像,使其完全覆盖组件,可能会裁剪部分图像。
  • BoxFit.fill: 非等比例拉伸或压缩图像以填充组件。
  • BoxFit.fitWidth: 等比例缩放图像,使其宽度与组件相等。
  • BoxFit.fitHeight: 等比例缩放图像,使其高度与组件相等。

repeat

  1. repeat: 在图像未填充满组件时,指定如何重复图像。常用选项包括:
  • ImageRepeat.noRepeat: 不重复,只显示一次图像。
  • ImageRepeat.repeat: 水平和垂直方向都重复图像。
  • ImageRepeat.repeatX: 水平方向重复图像。
  • ImageRepeat.repeatY: 垂直方向重复图像。

color

  1. color: 对图像进行着色的颜色。

colorBlendMode

colorBlendMode: 图像与着色颜色的混合模式。

  • BlendMode.clear:清除颜色。
  • BlendMode.src:只显示图像本身,忽略颜色。
  • BlendMode.dst:只显示颜色,忽略图像本身。
  • BlendMode.srcOver:将图像放在颜色之上。
  • BlendMode.dstOver:将颜色放在图像之上。
  • BlendMode.srcIn:只显示图像与颜色重叠的部分。
  • BlendMode.dstIn:只显示颜色与图像重叠的部分。
  • BlendMode.srcOut:只显示图像与颜色不重叠的部分。
  • BlendMode.dstOut:只显示颜色与图像不重叠的部分。
  • BlendMode.plus:将图像和颜色相加。
  • BlendMode.modulate:将图像和颜色进行调制。
  • BlendMode.screen:通过颜色的亮度增强图像。
  • BlendMode.overlay:叠加模式,根据颜色的亮度调整图像。

filterQuality

filterQuality: 图像的滤波质量,用于调整图像显示的平滑程度。


semanticLabel

semanticLabel: 图像的语义标签,用于无障碍功能。


三.1 示例代码

以下是一些常用Image属性的示例代码:

示例1:加载网络图像(NetworkImage)

Image(
  image: NetworkImage('https://example.com/image.jpg'), // 加载网络图像
  width: 200, // 设置图像宽度
  height: 200, // 设置图像高度
  fit: BoxFit.cover, // 图像适应方式为覆盖
)

示例2:加载Asset中的图像资源(AssetImage)

Image(
  image: AssetImage('assets/images/pic.jpeg'), // 加载Asset中的图像资源
  width: 200, // 设置图像宽度
  height: 200, // 设置图像高度
  fit: BoxFit.contain, // 图像适应方式为包含
)

图片的存放位置和设置

要加载AssetImage中的图像资源,您需要将图像文件放置在项目的assets/images/目录中。以下是一些步骤来加载AssetImage中的图像资源:

  1. 在Flutter项目的根目录下,创建一个名为assets/的文件夹(如果尚不存在)。
  2. assets/文件夹内,创建一个名为images/的子文件夹(如果尚不存在)。
  3. 将您的图像文件(例如,image.png)放入images/文件夹中。

接下来,您需要在pubspec.yaml文件中声明和配置您的图像资源。打开pubspec.yaml文件,并按照以下方式进行修改:

  1. flutter节下添加assets节,并在其中指定图像资源的路径:

    flutter:
      assets:
        - assets/images/pic.jpg
    

    这将告诉Flutter框架在构建应用程序时将这些图像资源打包到应用程序中。

image.png

示例3:加载本地文件系统中的图像文件(FileImage)

Image(
  image: FileImage(File('/path/to/image.jpg')), // 加载本地文件系统中的图像文件
  width: 200, // 设置图像宽度
  height: 200, // 设置图像高度
  fit: BoxFit.fill, // 图像适应方式为填充
)

这个就不演示了

示例4:加载内存中的图像数据(MemoryImage)

final bytes = await yourImageLoadingFunction(); // 获取图像数据
Image(
  image: MemoryImage(bytes), // 加载内存中的图像数据
  width: 200, // 设置图像宽度
  height: 200, // 设置图像高度
  fit: BoxFit.fitWidth, // 图像适应方式为宽度相等
)

三.2 细说fit 属性

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('图片适应效果演示'),
        ),
        body: SingleChildScrollView(
          child: Padding(
            padding: EdgeInsets.all(16.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                buildImageFitDemo(
                  fit: BoxFit.contain,
                  fitName: 'BoxFit.contain - 包含',
                ),
                SizedBox(height: 20),
                buildImageFitDemo(
                  fit: BoxFit.cover,
                  fitName: 'BoxFit.cover - 裁剪',
                ),
                SizedBox(height: 20),
                buildImageFitDemo(
                  fit: BoxFit.fill,
                  fitName: 'BoxFit.fill - 填充',
                ),
                SizedBox(height: 20),
                buildImageFitDemo(
                  fit: BoxFit.fitWidth,
                  fitName: 'BoxFit.fitWidth - 宽度填充',
                ),
                SizedBox(height: 20),
                buildImageFitDemo(
                  fit: BoxFit.fitHeight,
                  fitName: 'BoxFit.fitHeight - 高度填充',
                ),
                SizedBox(height: 20),
                buildImageFitDemo(
                  fit: BoxFit.scaleDown,
                  fitName: 'BoxFit.scaleDown - 缩小',
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Widget buildImageFitDemo({required BoxFit fit, required String fitName}) {
    return Column(
      children: [
        Text(
          fitName,
          style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
        ),
        SizedBox(height: 8),
        Container(
          width: 200,
          height: 200,
          decoration: BoxDecoration(
            border: Border.all(
              color: Colors.black,
              width: 2.0,
            ),
          ),
          child: Image.asset(
            'assets/images/pic.jpeg',
            fit: fit,
          ),
        ),
        SizedBox(height: 20),
      ],
    );
  }
}

image.png

三.3 细说混色 colorBlendMode 属性

一些常用的 BlendMode 值及其效果:

  • BlendMode.clear:清除颜色。
  • BlendMode.src:只显示图像本身,忽略颜色。
  • BlendMode.dst:只显示颜色,忽略图像本身。
  • BlendMode.srcOver:将图像放在颜色之上。
  • BlendMode.dstOver:将颜色放在图像之上。
  • BlendMode.srcIn:只显示图像与颜色重叠的部分。
  • BlendMode.dstIn:只显示颜色与图像重叠的部分。
  • BlendMode.srcOut:只显示图像与颜色不重叠的部分。
  • BlendMode.dstOut:只显示颜色与图像不重叠的部分。
  • BlendMode.plus:将图像和颜色相加。
  • BlendMode.modulate:将图像和颜色进行调制。
  • BlendMode.screen:通过颜色的亮度增强图像。
  • BlendMode.overlay:叠加模式,根据颜色的亮度调整图像。
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('图像混合模式演示'),
        ),
        body: SingleChildScrollView(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ImageBlendModeDemo(
                image: AssetImage('assets/images/pic.png'),
                blendMode: BlendMode.clear,
                blendModeName: 'BlendMode.clear - 清除',
                color: Colors.red,
              ),
              SizedBox(height: 20),
              ImageBlendModeDemo(
                image: AssetImage('assets/images/pic.png'),
                blendMode: BlendMode.src,
                blendModeName: 'BlendMode.src - 保持图像',
                color: Colors.red,
              ),
              SizedBox(height: 20),
              ImageBlendModeDemo(
                image: AssetImage('assets/images/pic.png'),
                blendMode: BlendMode.dst,
                blendModeName: 'BlendMode.dst - 保持颜色',
                color: Colors.red,
              ),
              SizedBox(height: 20),
              ImageBlendModeDemo(
                image: AssetImage('assets/images/pic.png'),
                blendMode: BlendMode.srcOver,
                blendModeName: 'BlendMode.srcOver - 图像在顶部',
                color: Colors.red,
              ),
              SizedBox(height: 20),
              ImageBlendModeDemo(
                image: AssetImage('assets/images/pic.png'),
                blendMode: BlendMode.dstOver,
                blendModeName: 'BlendMode.dstOver - 颜色在顶部',
                color: Colors.red,
              ),
              SizedBox(height: 20),
              ImageBlendModeDemo(
                image: AssetImage('assets/images/pic.png'),
                blendMode: BlendMode.srcIn,
                blendModeName: 'BlendMode.srcIn - 图像与颜色重叠部分',
                color: Colors.red,
              ),
              SizedBox(height: 20),
              ImageBlendModeDemo(
                image: AssetImage('assets/images/pic.png'),
                blendMode: BlendMode.dstIn,
                blendModeName: 'BlendMode.dstIn - 颜色与图像重叠部分',
                color: Colors.red,
              ),
              SizedBox(height: 20),
              ImageBlendModeDemo(
                image: AssetImage('assets/images/pic.png'),
                blendMode: BlendMode.srcOut,
                blendModeName: 'BlendMode.srcOut - 图像与颜色不重叠部分',
                color: Colors.red,
              ),
              SizedBox(height: 20),
              ImageBlendModeDemo(
                image: AssetImage('assets/images/pic.png'),
                blendMode: BlendMode.dstOut,
                blendModeName: 'BlendMode.dstOut - 颜色与图像不重叠部分',
                color: Colors.red,
              ),
              SizedBox(height: 20),
              ImageBlendModeDemo(
                image: AssetImage('assets/images/pic.png'),
                blendMode: BlendMode.plus,
                blendModeName: 'BlendMode.plus - 图像和颜色相加',
                color: Colors.red,
              ),
              SizedBox(height: 20),
              ImageBlendModeDemo(
                image: AssetImage('assets/images/pic.png'),
                blendMode: BlendMode.modulate,
                blendModeName: 'BlendMode.modulate - 图像和颜色调制',
                color: Colors.red,
              ),
              SizedBox(height: 20),
              ImageBlendModeDemo(
                image: AssetImage('assets/images/pic.png'),
                blendMode: BlendMode.screen,
                blendModeName: 'BlendMode.screen - 滤色',
                color: Colors.red,
              ),
              SizedBox(height: 20),
              ImageBlendModeDemo(
                image: AssetImage('assets/images/pic.png'),
                blendMode: BlendMode.overlay,
                blendModeName: 'BlendMode.overlay - 叠加',
                color: Colors.red,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class ImageBlendModeDemo extends StatelessWidget {
  final ImageProvider image;
  final BlendMode blendMode;
  final String blendModeName;
  final Color color;

  ImageBlendModeDemo({
    required this.image,
    required this.blendMode,
    required this.blendModeName,
    required this.color,
  });

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text(
          blendModeName,
          style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
        ),
        SizedBox(height: 8),
        ColorFiltered(
          colorFilter: ColorFilter.mode(color, blendMode),
          child: Image(
            image: image,
            width: 50,
            height: 50,
          ),
        ),
        SizedBox(height: 20),
      ],
    );
  }
}

image.png

image.png

image.png

三.3 细说 repeat 属性

在Flutter中,Image组件的repeat属性用于定义图像在渲染时的重复方式。通过设置repeat属性,您可以控制图像在未完全填充容器时的重复方式。

repeat属性是一个ImageRepeat枚举类型,它定义了不同的重复模式。以下是ImageRepeat枚举的常见取值:

  • ImageRepeat.noRepeat:图像不进行重复,只显示一次,默认值。
  • ImageRepeat.repeat:图像在水平和垂直方向上重复。
  • ImageRepeat.repeatX:图像在水平方向上重复。
  • ImageRepeat.repeatY:图像在垂直方向上重复。
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('图像重复模式演示'),
        ),
        body: SingleChildScrollView(
          child: Column(
            children: [
              ListView(
                shrinkWrap: true,
                physics: NeverScrollableScrollPhysics(),
                children: [
                  ImageRepeatDemo(
                    repeat: ImageRepeat.noRepeat,
                    repeatName: 'ImageRepeat.noRepeat - 不重复',
                  ),
                  SizedBox(height: 20),
                  ImageRepeatDemo(
                    repeat: ImageRepeat.repeat,
                    repeatName: 'ImageRepeat.repeat - 全部重复',
                  ),
                  SizedBox(height: 20),
                  ImageRepeatDemo(
                    repeat: ImageRepeat.repeatX,
                    repeatName: 'ImageRepeat.repeatX - 水平重复',
                  ),
                  SizedBox(height: 20),
                  ImageRepeatDemo(
                    repeat: ImageRepeat.repeatY,
                    repeatName: 'ImageRepeat.repeatY - 垂直重复',
                  ),
                  SizedBox(height: 20),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class ImageRepeatDemo extends StatelessWidget {
  final ImageRepeat repeat;
  final String repeatName;

  ImageRepeatDemo({required this.repeat, required this.repeatName});

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text(repeatName),
        Container(
          width: 150,
          height: 150,
          decoration: BoxDecoration(
            border: Border.all(
              color: Colors.black,
              width: 2.0,
            ),
          ),
          child: Image.asset(
            'assets/images/small_pic.png',
            repeat: repeat,
          ),
        ),
      ],
    );
  }
}

image.png

四 注意点

在日常开发中,使用Image组件时需要注意以下几点:

  • 图像加载性能:注意图像的大小和分辨率,避免加载过大的图像,以提高应用性能。
  • 图像缓存:Flutter内部提供了图像缓存机制,可以自动管理图像的缓存和释放。对于频繁显示的图像,使用缓存可以提高性能和用户体验。
  • 适当调整图像大小:根据实际需求和显示情况,可以使用widthheight属性来调整图像的显示大小,避免过度拉伸或压缩。
  • 注意图像适应方式和重复方式:根据实际情况选择适当的fitrepeat属性,以确保图像在组件内得到正确的展示效果。
  • 图像的无障碍功能:使用semanticLabel属性为图像提供有意义的语义标签,以支持无障碍功能。

高级特性:

  • 自定义图像加载和缓存:Flutter提供了丰富的图像加载和缓存库,如cached_network_image、flutter_cached_network_image等,可以根据需求选择适合的库来实现自定义的图像加载和缓存策略。