本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

一、Flutter 中主要的 Image 组件

Flutter 提供了多种 Image 组件用于加载和显示图片,主要分为以下几类:

1. Image (基本图片组件)

import 'package:flutter/material.dart';

Image(
  image: AssetImage('assets/images/example.png'),
  width: 100,
  height: 100,
)

2. Image.network (网络图片)

Image.network(
  'https://example.com/image.jpg',
  width: 200,
  height: 200,
)

3. Image.asset (本地资源图片)

Image.asset(
  'assets/images/logo.png',
  width: 150,
  height: 150,
)

4. Image.file (本地文件图片)

Image.file(
  File('/storage/emulated/0/Download/image.jpg'),
  width: 200,
  height: 200,
)

5. Image.memory (内存图片)

Image.memory(
  Uint8List.fromList(imageBytes),
  width: 100,
  height: 100,
)

6. FadeInImage (渐入图片)

FadeInImage(
  placeholder: AssetImage('assets/loading.gif'),
  image: NetworkImage('https://example.com/image.jpg'),
  width: 200,
  height: 200,
)

7. CircleAvatar (圆形头像)

CircleAvatar(
  backgroundImage: NetworkImage('https://example.com/avatar.jpg'),
  radius: 50,
)

8. DecorationImage (装饰图片)

Container(
  decoration: BoxDecoration(
    image: DecorationImage(
      image: AssetImage('assets/background.jpg'),
      fit: BoxFit.cover,
    ),
  ),
)

二、区别对比

组件类型 来源 主要用途 特点
Image 多种来源 通用图片显示 需要指定 ImageProvider
Image.network 网络URL 显示网络图片 自动缓存,支持进度
Image.asset 本地资源 显示应用内图片 编译时打包,性能好
Image.file 本地文件 显示设备文件 需要文件权限
Image.memory 内存数据 显示字节数据 适合动态生成图片
FadeInImage 混合来源 带占位图的图片 提供平滑过渡效果
CircleAvatar 多种来源 显示圆形头像 内置圆形裁剪
DecorationImage 多种来源 作为背景图片 配合Container使用

三、详细用法

1. Image.network - 网络图片(最常用)

Image.network(
  'https://picsum.photos/300/300',
  width: 300,
  height: 200,
  
  // 加载配置
  loadingBuilder: (context, child, loadingProgress) {
    if (loadingProgress == null) return child;
    return Center(
      child: CircularProgressIndicator(
        value: loadingProgress.expectedTotalBytes != null
            ? loadingProgress.cumulativeBytesLoaded / 
              loadingProgress.expectedTotalBytes!
            : null,
      ),
    );
  },
  
  // 错误处理
  errorBuilder: (context, error, stackTrace) {
    return Icon(Icons.error, color: Colors.red, size: 50);
  },
  
  // 图片适配模式
  fit: BoxFit.cover,
  
  // 对齐方式
  alignment: Alignment.center,
  
  // 重复方式
  repeat: ImageRepeat.noRepeat,
  
  // 颜色混合
  color: Colors.blue.withOpacity(0.5),
  colorBlendMode: BlendMode.overlay,
  
  // 缓存配置
  cacheWidth: 300, // 指定缓存宽度
  cacheHeight: 200, // 指定缓存高度
  
  // 语义标签
  semanticLabel: 'A beautiful landscape photo',
  
  // 排除语义(用于装饰性图片)
  excludeFromSemantics: false,
  
  // 过滤器质量
  filterQuality: FilterQuality.high,
  
  // 是否为抗锯齿
  isAntiAlias: true,
  
  // 匹配文本方向
  matchTextDirection: false,
  
  // 图片方向
  gaplessPlayback: true,
)

2. Image.asset - 资源图片

// 基本用法
Image.asset(
  'assets/images/logo.png',
  width: 200,
  height: 100,
  fit: BoxFit.contain,
)

// 使用不同分辨率的图片(自动适配)
Image.asset(
  'assets/images/logo.png',
  width: 100,
  height: 100,
  // 系统会根据设备像素密度自动选择:
  // logo.png
  // 2.0x/logo.png
  // 3.0x/logo.png
  // 4.0x/logo.png
)

// 指定包名(package)
Image.asset(
  'assets/icon.png',
  package: 'third_party_package',
)

// 配置 pubspec.yaml
// flutter:
//   assets:
//     - assets/images/logo.png
//     - assets/images/background.jpg
//     - assets/images/icons/

3. Image.file - 文件图片

import 'dart:io';
import 'package:flutter/material.dart';

// 基本用法
Image.file(
  File('/path/to/image.jpg'),
  width: 200,
  height: 200,
)

// 完整示例(需要权限)
class FileImageExample extends StatefulWidget {
  @override
  _FileImageExampleState createState() => _FileImageExampleState();
}

class _FileImageExampleState extends State<FileImageExample> {
  File? _imageFile;

  // 从图库选择图片
  Future<void> _pickImage() async {
    // 使用 image_picker 包
    // final pickedFile = await ImagePicker().pickImage(source: ImageSource.gallery);
    // if (pickedFile != null) {
    //   setState(() {
    //     _imageFile = File(pickedFile.path);
    //   });
    // }
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        if (_imageFile != null)
          Image.file(
            _imageFile!,
            width: 200,
            height: 200,
            fit: BoxFit.cover,
            errorBuilder: (context, error, stackTrace) {
              return Container(
                width: 200,
                height: 200,
                color: Colors.grey[300],
                child: Center(
                  child: Text('加载失败'),
                ),
              );
            },
          )
        else
          Container(
            width: 200,
            height: 200,
            color: Colors.grey[300],
            child: Center(
              child: Icon(Icons.photo, size: 50, color: Colors.grey[600]),
            ),
          ),
        
        ElevatedButton(
          onPressed: _pickImage,
          child: Text('选择图片'),
        ),
      ],
    );
  }
}

4. FadeInImage - 带占位图的图片

// 网络图片 + Asset占位图
FadeInImage(
  placeholder: AssetImage('assets/placeholder.jpg'),
  image: NetworkImage('https://example.com/image.jpg'),
  width: 300,
  height: 200,
  fit: BoxFit.cover,
  fadeInDuration: Duration(milliseconds: 500),
  fadeOutDuration: Duration(milliseconds: 300),
  fadeInCurve: Curves.easeIn,
  fadeOutCurve: Curves.easeOut,
)

// 内存占位图
FadeInImage.memoryNetwork(
  placeholder: kTransparentImage, // 使用透明占位图
  image: 'https://example.com/image.jpg',
  width: 300,
  height: 200,
)

// 使用内置加载指示器
FadeInImage.assetNetwork(
  placeholder: 'assets/loading.gif',
  image: 'https://example.com/image.jpg',
  placeholderScale: 1.0,
  imageErrorBuilder: (context, error, stackTrace) {
    return Container(
      color: Colors.grey[200],
      child: Center(
        child: Icon(Icons.broken_image, size: 50),
      ),
    );
  },
)

5. CircleAvatar - 圆形头像

// 基础用法
CircleAvatar(
  backgroundImage: NetworkImage('https://example.com/avatar.jpg'),
  radius: 50,
)

// 完整配置
CircleAvatar(
  backgroundImage: AssetImage('assets/avatar.png'),
  backgroundColor: Colors.blue, // 图片加载失败时的背景色
  foregroundColor: Colors.white, // 前景色(用于child)
  radius: 60,
  minRadius: 40, // 最小半径
  maxRadius: 80, // 最大半径
  
  // 自定义child
  child: Text(
    'JS',
    style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
  ),
  
  // 点击事件
  onBackgroundImageError: (exception, stackTrace) {
    print('头像加载失败: $exception');
  },
)

// 在ListTile中使用
ListTile(
  leading: CircleAvatar(
    backgroundImage: NetworkImage('https://example.com/user1.jpg'),
  ),
  title: Text('张三'),
  subtitle: Text('前端工程师'),
)

6. DecorationImage - 背景图片

Container(
  width: 300,
  height: 200,
  decoration: BoxDecoration(
    image: DecorationImage(
      image: NetworkImage('https://example.com/background.jpg'),
      
      // 适配模式
      fit: BoxFit.cover, // 常用值:cover, contain, fill, fitWidth, fitHeight
      
      // 对齐方式
      alignment: Alignment.center,
      
      // 重复方式
      repeat: ImageRepeat.noRepeat, // 或 repeat, repeatX, repeatY
      
      // 颜色过滤
      colorFilter: ColorFilter.mode(
        Colors.black.withOpacity(0.3),
        BlendMode.darken,
      ),
      
      // 匹配文本方向
      matchTextDirection: false,
      
      // 是否抗锯齿
      isAntiAlias: true,
      
      // 过滤器质量
      filterQuality: FilterQuality.high,
      
      // 反转
      invertColors: false,
      
      // 缩放
      scale: 1.0,
      
      // 仅用于缓存宽度/高度
      // cacheWidth: 300,
      // cacheHeight: 200,
    ),
    
    // 其他装饰
    borderRadius: BorderRadius.circular(12),
    border: Border.all(color: Colors.grey, width: 1),
  ),
  child: Center(
    child: Text(
      '背景图片',
      style: TextStyle(color: Colors.white, fontSize: 24),
    ),
  ),
)

四、高级用法

图片缓存管理

// 使用CachedNetworkImage(第三方包)
CachedNetworkImage(
  imageUrl: "https://example.com/image.jpg",
  placeholder: (context, url) => CircularProgressIndicator(),
  errorWidget: (context, url, error) => Icon(Icons.error),
  fit: BoxFit.cover,
  
  // 缓存配置
  cacheManager: CacheManager(
    Config(
      'customCacheKey',
      stalePeriod: Duration(days: 7),
      maxNrOfCacheObjects: 100,
    ),
  ),
  
  // 使用缓存宽度高度
  memCacheWidth: 300,
  memCacheHeight: 200,
  
  // 过滤器质量
  filterQuality: FilterQuality.medium,
)

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐