You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter实现Image Picker选图后裁剪保存(类WhatsApp头像上传)

在Flutter实现类似WhatsApp的头像上传功能

嘿,我来帮你搞定Flutter里类似WhatsApp的头像上传功能!核心就是选图→圆形裁剪→保存这三步,我把每个环节需要的包、代码示例都整理好了,跟着做就行~

一、先准备依赖包

首先得引入几个专门处理不同环节的包,直接在pubspec.yaml里加:

dependencies:
  flutter:
    sdk: flutter
  image_picker: ^1.0.4  # 用来选相册/相机图片
  image_cropper: ^5.0.0  # 实现圆形裁剪界面
  path_provider: ^2.1.1  # 获取本地存储路径
  permission_handler: ^10.2.0  # 处理相机/相册权限(可选但推荐,避免踩坑)

加完之后执行flutter pub get安装这些包。

二、实现图片选择功能

写个简单的方法,让用户从相册选图(要相机的话改下参数就行):

import 'package:image_picker/image_picker.dart';

Future<XFile?> pickAvatarImage() async {
  final picker = ImagePicker();
  // 选相册:ImageSource.gallery,选相机:ImageSource.camera
  final XFile? pickedImage = await picker.pickImage(source: ImageSource.gallery);
  return pickedImage;
}

三、核心:圆形裁剪(和WhatsApp一模一样!)

拿到选中的图片后,调用image_cropper做圆形裁剪,这里的配置直接对齐WhatsApp的风格:

import 'package:image_cropper/image_cropper.dart';

Future<CroppedFile?> cropAvatar(XFile image) async {
  final CroppedFile? croppedImage = await ImageCropper().cropImage(
    sourcePath: image.path,
    aspectRatio: const CropAspectRatio(ratioX: 1, ratioY: 1), // 强制1:1比例
    cropStyle: CropStyle.circle, // 直接裁剪成圆形
    uiSettings: [
      AndroidUiSettings(
        toolbarTitle: '裁剪头像',
        toolbarColor: const Color(0xff25D366), // WhatsApp的绿色工具栏
        toolbarWidgetColor: Colors.white,
        lockAspectRatio: true, // 锁定比例,用户不能拉歪
      ),
      IOSUiSettings(
        title: '裁剪头像',
        aspectRatioLockEnabled: true,
      ),
    ],
  );
  return croppedImage;
}

四、保存裁剪后的头像

把裁剪好的图片存到应用的本地目录,方便后续显示或上传服务器:

import 'dart:io';
import 'package:path_provider/path_provider.dart';

Future<File> saveCroppedAvatar(CroppedFile croppedImage) async {
  final appDir = await getApplicationDocumentsDirectory();
  // 用时间戳当文件名,避免重复
  final fileName = 'avatar_${DateTime.now().millisecondsSinceEpoch}.png';
  final savedFile = File('${appDir.path}/$fileName');
  // 复制裁剪后的图片到目标路径
  await File(croppedImage.path).copy(savedFile.path);
  return savedFile;
}

五、整合到UI按钮

把上面的步骤串起来,加到一个按钮的点击事件里:

// 先定义个变量存头像路径
String? _avatarPath;

// 按钮代码
ElevatedButton(
  style: ElevatedButton.styleFrom(backgroundColor: const Color(0xff25D366)),
  onPressed: () async {
    try {
      // 1. 选图
      final pickedImage = await pickAvatarImage();
      if (pickedImage == null) return;

      // 2. 裁剪
      final croppedImage = await cropAvatar(pickedImage);
      if (croppedImage == null) return;

      // 3. 保存
      final savedImage = await saveCroppedAvatar(croppedImage);

      // 更新UI显示头像
      setState(() {
        _avatarPath = savedImage.path;
      });
    } catch (e) {
      // 这里可以加错误提示,比如Toast
      print('头像处理出错:$e');
    }
  },
  child: const Text('更换头像', style: TextStyle(color: Colors.white)),
)

六、显示最终的头像

用CircleAvatar来展示,完美贴合WhatsApp的头像样式:

CircleAvatar(
  radius: 50,
  backgroundImage: _avatarPath != null ? FileImage(File(_avatarPath!)) : null,
  child: _avatarPath == null ? const Icon(Icons.person, size: 50) : null,
)

小提醒

  • 权限:如果用到相机,记得在Android的AndroidManifest.xml和iOS的Info.plist里添加权限声明,用permission_handler提前申请权限,不然会崩溃哦。
  • 错误处理:实际开发中记得加try-catch,处理用户中途取消选图、裁剪的情况。
  • 自定义:如果想调整裁剪界面的样式,直接修改uiSettings里的参数就行。

内容的提问来源于stack exchange,提问作者Prasanth Kanna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:52:23