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

Flutter如何将Widget转PNG图片并保存到内部存储自定义创建的目录

Flutter 应用专属目录创建+Widget转PNG保存完整实现

1. 添加依赖

先在项目根目录的pubspec.yaml中添加如下依赖:

dependencies:
  flutter:
    sdk: flutter
  # 用于Widget转图片
  screenshot: ^2.1.0
  # 用于获取应用存储路径
  path_provider: ^2.1.1
  # 用于路径拼接处理
  path: ^1.8.3
  # 用于判断首次安装
  shared_preferences: ^2.2.2

添加后执行flutter pub get安装依赖。

2. 核心实现代码

直接替换lib/main.dart内容即可,所有逻辑都加了注释可直接修改:

import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:screenshot/screenshot.dart';
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';

// 全局存储专属目录路径
late String saveDirPath;

void main() async {
  // 初始化Flutter绑定
  WidgetsFlutterBinding.ensureInitialized();
  // 初始化SharedPreferences
  final prefs = await SharedPreferences.getInstance();
  // 获取应用内部文档目录(专属目录,无需申请存储权限)
  final appDocDir = await getApplicationDocumentsDirectory();
  saveDirPath = '${appDocDir.path}/custom_screenshots';

  // 判断是否首次安装
  bool isFirstRun = prefs.getBool('first_run') ?? true;
  if (isFirstRun) {
    // 创建专属目录,recursive为true表示父目录不存在时一并创建
    await Directory(saveDirPath).create(recursive: true);
    // 标记已非首次启动
    await prefs.setBool('first_run', false);
  }

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Widget转PNG demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  // 实例化截图控制器
  final ScreenshotController _screenshotController = ScreenshotController();

  // 保存截图的方法
  Future<void> saveWidgetToPng() async {
    try {
      // 截取目标Widget为Uint8List格式
      Uint8List? imageBytes = await _screenshotController.capture();
      if (imageBytes == null) {
        if(mounted) {
          ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('截图失败,请重试')));
        }
        return;
      }
      // 生成保存路径,用时间戳作为文件名避免重复
      String savePath = '$saveDirPath/${DateTime.now().millisecondsSinceEpoch}.png';
      // 写入文件
      await File(savePath).writeAsBytes(imageBytes);
      if(mounted) {
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('图片已保存至:$savePath')));
      }
    } catch (e) {
      if(mounted) {
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('保存失败:$e')));
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Widget转PNG示例')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // 用Screenshot包裹需要转成PNG的目标Widget,可替换为任意自定义页面
            Screenshot(
              controller: _screenshotController,
              child: Container(
                width: 300,
                height: 300,
                color: Colors.white,
                child: const Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Icon(Icons.flutter_dash, size: 100, color: Colors.blue),
                    Text(
                      '我是要被转成PNG的内容',
                      style: TextStyle(fontSize: 18, color: Colors.black),
                    )
                  ],
                ),
              ),
            ),
            const SizedBox(height: 40),
            // 触发截图保存的按钮
            ElevatedButton(
              onPressed: saveWidgetToPng,
              child: const Text('点击将上方Widget保存为PNG'),
            )
          ],
        ),
      ),
    );
  }
}

3. 功能说明

  • 首次安装逻辑:应用首次启动时会自动在应用内部专属文档目录下创建custom_screenshots文件夹,该目录仅当前应用可访问,无需申请任何存储权限
  • 可自定义截图范围:只需将需要转成PNG的Widget用Screenshot组件包裹即可,支持普通Widget、列表、自定义页面等所有Flutter组件
  • 保存逻辑:图片按时间戳命名,避免覆盖,保存成功后会弹出路径提示,可根据需求调整命名规则和存储路径

内容的提问来源于stack exchange,提问作者Mohammad Alamoudi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 16:06:10