记录下,把页面红色区域内的内容,转成图片后保存到相册的功能
依赖
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">