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

一、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

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

更多推荐