125 lines
3.7 KiB
Dart
125 lines
3.7 KiB
Dart
import 'dart:io';
|
|
import 'dart:typed_data';
|
|
import 'dart:ui' as ui;
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/rendering.dart';
|
|
import 'package:flutter_common/utils/toast_util.dart';
|
|
import 'package:path_provider/path_provider.dart';
|
|
import 'package:share_plus/share_plus.dart';
|
|
|
|
/// 截图工具类
|
|
class ScreenshotUtil {
|
|
static double pixelRatio = 3.0;
|
|
static Duration delay = const Duration(milliseconds: 50);
|
|
static String watermarkText = '来自 食光集';
|
|
|
|
// 截图功能
|
|
static Future<Uint8List?> captureImage({required GlobalKey globalKey}) async {
|
|
// 等待一帧确保UI已渲染
|
|
await Future.delayed(delay);
|
|
final RenderObject? render = globalKey.currentContext!.findRenderObject();
|
|
final RenderRepaintBoundary boundary = render as RenderRepaintBoundary;
|
|
final ui.Image image = await boundary.toImage(pixelRatio: pixelRatio);
|
|
|
|
// 添加水印
|
|
return await _addWatermarkToImage(image);
|
|
}
|
|
|
|
// 添加水印到图片
|
|
static Future<Uint8List> _addWatermarkToImage(ui.Image image) async {
|
|
// 创建画布
|
|
final recorder = ui.PictureRecorder();
|
|
final canvas = Canvas(recorder);
|
|
|
|
// 绘制原始图片
|
|
canvas.drawImage(image, Offset.zero, Paint());
|
|
|
|
// 添加文字水印
|
|
_drawTextWatermark(canvas, image);
|
|
|
|
// 生成最终图片
|
|
final picture = recorder.endRecording();
|
|
final watermarkedImage = await picture.toImage(image.width, image.height);
|
|
final ByteData? byteData = await watermarkedImage.toByteData(
|
|
format: ui.ImageByteFormat.png,
|
|
);
|
|
|
|
return byteData!.buffer.asUint8List();
|
|
}
|
|
|
|
// 绘制文字水印
|
|
static void _drawTextWatermark(Canvas canvas, ui.Image image) {
|
|
final textPainter = TextPainter(
|
|
text: TextSpan(
|
|
text: watermarkText,
|
|
style: TextStyle(
|
|
color: Color(0x99FFFFFF),
|
|
fontSize: 28,
|
|
fontFamily: 'CustomFont',
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
textDirection: TextDirection.ltr,
|
|
);
|
|
|
|
textPainter.layout(maxWidth: image.width.toDouble());
|
|
|
|
// 计算水印位置(右下角,带边距)
|
|
final double x = image.width - textPainter.width - 40;
|
|
final double y = image.height - textPainter.height - 40;
|
|
|
|
// 绘制文字背景
|
|
final backgroundPaint =
|
|
Paint()
|
|
..color = const ui.Color(0x4D000000)
|
|
..style = PaintingStyle.fill;
|
|
|
|
// 绘制圆角矩形背景
|
|
final backgroundRect = RRect.fromRectAndRadius(
|
|
Rect.fromLTWH(
|
|
x - 12,
|
|
y - 6,
|
|
textPainter.width + 24,
|
|
textPainter.height + 12,
|
|
),
|
|
Radius.circular(6),
|
|
);
|
|
canvas.drawRRect(backgroundRect, backgroundPaint);
|
|
|
|
// 绘制文字
|
|
textPainter.paint(canvas, Offset(x, y));
|
|
}
|
|
|
|
// 保存图片到临时文件
|
|
static Future<File> saveImageToFile(Uint8List bytes, String fileName) async {
|
|
final directory = await getTemporaryDirectory();
|
|
final File imageFile = File('${directory.path}/$fileName');
|
|
await imageFile.writeAsBytes(bytes);
|
|
return imageFile;
|
|
}
|
|
|
|
static Future<void> captureAndShare({
|
|
required GlobalKey globalKey,
|
|
required String fileName,
|
|
required String shareText,
|
|
}) async {
|
|
try {
|
|
final imageBytes = await captureImage(globalKey: globalKey);
|
|
|
|
if (imageBytes != null) {
|
|
final imageFile = await saveImageToFile(imageBytes, fileName);
|
|
await SharePlus.instance.share(
|
|
ShareParams(files: [XFile(imageFile.path)], text: shareText),
|
|
);
|
|
|
|
// 分享后删除临时文件
|
|
await imageFile.delete();
|
|
} else {
|
|
ToastUtil.error('生成图片失败,请重试');
|
|
}
|
|
} catch (e) {
|
|
ToastUtil.error('分享失败: $e');
|
|
}
|
|
}
|
|
}
|