Flutter:邀请海报,Widget转图片,保存相册

记录下,把页面红色区域内的内容,转成图片后保存到相册的功能

依赖

js 复制代码
# 生成二维码
qr_flutter: ^4.1.0
# 保存图片
image_gallery_saver_plus: ^3.0.5

view

js 复制代码
import 'package:demo/common/index.dart';
import 'package:ducafe_ui_core/ducafe_ui_core.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'package:tdesign_flutter/tdesign_flutter.dart';

import 'index.dart';

class SharePage extends GetView<ShareController> {
  const SharePage({super.key});

  // 主视图
  Widget _buildView() {
    return RepaintBoundary(
      key: controller.qrKey,
      child: <Widget>[
        TDImage(
          assetUrl: 'assets/img/user.png',
          width: 100.w,
          height: 100.w,
        ),
        TextWidget.body('邀请码:10086', size: 40.sp),
        QrImageView(
          data: '10086',
          version: QrVersions.auto,
          size: 400.w,
          gapless: false,
          embeddedImage: const AssetImage('assets/img/user.png'),
          embeddedImageStyle: QrEmbeddedImageStyle(
            size: Size(100.w, 100.w),
          ),
        ),
      ].toColumn(
        crossAxisAlignment: CrossAxisAlignment.center,
        mainAxisAlignment: MainAxisAlignment.center,
      ).card(color: Colors.white).tight(width: 750.w, height: 750.w),
    );
  }

  @override
  Widget build(BuildContext context) {
    return GetBuilder<ShareController>(
      init: ShareController(),
      id: "share",
      builder: (_) {
        return Scaffold(
          backgroundColor: const Color(0xffF5F6FA),
          appBar: TDNavBar(
            height: 45,
            title: '邀请码',
            titleFontWeight: FontWeight.w600,
            backgroundColor: Colors.white,
            screenAdaptation: true,
            useDefaultBack: true,
            rightBarItems: [
              TDNavBarItem(
                iconWidget: Text('保存'),
                action: controller.saveQrCode,
              ),
            ],
          ),
          body: SafeArea(
            child: _buildView(),
          ),
        );
      },
    );
  }
}

controller

js 复制代码
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:get/get.dart';
import 'package:image_gallery_saver_plus/image_gallery_saver_plus.dart';

class ShareController extends GetxController {
  final GlobalKey qrKey = GlobalKey();
  
  Future<void> saveQrCode() async {
    try {
      // 获取 RenderRepaintBoundary
      final boundary = qrKey.currentContext!
          .findRenderObject() as RenderRepaintBoundary;
      
      // 等待一下确保UI已经完全渲染
      await Future.delayed(const Duration(milliseconds: 20));
      
      // 将 Widget 转换成图片
      final image = await boundary.toImage(pixelRatio: 3.0);
      
      // 将图片转换成字节数据
      final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
      
      if (byteData != null) {
        // 使用 image_gallery_saver_plus 保存到相册
        final result = await ImageGallerySaverPlus.saveImage(
          byteData.buffer.asUint8List(),
          quality: 100,
          name: "qr_code_${DateTime.now().millisecondsSinceEpoch}"
        );
        
        if (result != null && result['isSuccess']) {
          Get.snackbar('提示', '保存成功');
        } else {
          Get.snackbar('提示', '保存失败,请确保已授予存储权限');
        }
      }
    } catch (e) {
      print('保存失败:$e');
      Get.snackbar('提示', '保存失败,请确保已授予存储权限');
    }
  }
}

AndroidManifest.xml 权限配置

js 复制代码
<!-- 允许应用写入外部存储 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 允许应用读取外部存储 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!-- 允许应用读取媒体图像 -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<application
	android:requestLegacyExternalStorage="true">
相关推荐
桂月二二14 小时前
解锁2025编程新高度:深入探索编程技术的最新趋势
前端·人工智能·flutter·neo4j·wasm
lichong95117 小时前
【Flutter&Dart】 拖动改变 widget 的窗口尺寸大小GestureDetector~简单实现(10 /100)
android·flutter·api·postman·smartapi·postapi·foxapi
low神17 小时前
Flutter路由钩子
前端·javascript·flutter·前端面试题
sunly_17 小时前
Flutter:打包apk,安卓版本更新(二)
android·flutter
折翅鵬17 小时前
Flutter踩坑记-第三方SDK不兼容Gradle 8.0,需适配namespace
flutter
LuiChun1 天前
Flutter中的网络请求图片存储为缓存,与定制删除本地缓存
flutter·缓存
leluckys2 天前
flutter 专题二十四 Flutter性能优化在携程酒店的实践
flutter·性能优化
西辰Knight2 天前
【Flutter入门】2. 快速掌握Dart语言 - 从 Java、JavaScript 转型必看
flutter·dart
weixin_460783872 天前
Flutter Android修改应用名称、应用图片、应用启动画面
android·flutter
轻口味2 天前
【每日学点鸿蒙知识】RelativeContainer组件、List回弹、Flutter方法调用、Profiler工具等
flutter·list·harmonyos