Files
ai_chat_assistant/lib/widgets/_hole_overlay.dart

107 lines
2.9 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
// 一个带洞的遮罩层点击洞外区域触发onTap事件
class HoleOverlay extends StatelessWidget {
final Offset iconPosition;
final double iconSize;
final VoidCallback? onTap;
final Widget? child;
const HoleOverlay({
super.key,
required this.iconPosition,
required this.iconSize,
this.onTap,
this.child,
});
@override
Widget build(BuildContext context) {
debugPrint('🔧 HoleOverlay build: iconPosition=$iconPosition, iconSize=$iconSize');
final holeRect = Rect.fromLTWH(
iconPosition.dx,
iconPosition.dy,
iconSize,
iconSize,
);
return CustomPaint(
painter: _HolePainter(
iconPosition: iconPosition,
iconSize: iconSize,
),
child: GestureDetector(
onTapDown: (details) {
final tapPosition = details.localPosition;
final isInHole = holeRect.contains(tapPosition);
debugPrint('🎯 HoleOverlay onTapDown: position=$tapPosition, holeRect=$holeRect, isInHole=$isInHole');
if (!isInHole) {
debugPrint('🔥 HoleOverlay: 点击洞外触发onTap');
onTap?.call();
} else {
debugPrint('🚫 HoleOverlay: 点击洞内不触发onTap');
}
},
child: child,
behavior: HitTestBehavior.translucent,
),
);
}
}
class _HolePainter extends CustomPainter {
final Offset iconPosition;
final double iconSize;
_HolePainter({
required this.iconPosition,
required this.iconSize,
});
@override
void paint(Canvas canvas, Size size) {
final holeRect = Rect.fromLTWH(
iconPosition.dx,
iconPosition.dy,
iconSize,
iconSize,
);
debugPrint('🎨 HolePainter paint: size=$size, holeRect=$holeRect');
// 使用 saveLayer 确保混合模式正确
canvas.saveLayer(Offset.zero & size, Paint());
// 画半透明背景
final backgroundPaint = Paint()
..color = Colors.black.withOpacity(0.3);
canvas.drawRect(Offset.zero & size, backgroundPaint);
debugPrint('🔲 HolePainter paint: 绘制背景完成');
// 挖洞:使用 BlendMode.clear
final holePaint = Paint()
..blendMode = BlendMode.clear;
canvas.drawOval(holeRect, holePaint);
debugPrint('⭕ HolePainter paint: 挖洞完成holeRect=$holeRect');
canvas.restore();
// 调试:画红色边框显示洞的位置
final debugPaint = Paint()
..color = Colors.red
..style = PaintingStyle.stroke
..strokeWidth = 2.0;
canvas.drawOval(holeRect, debugPaint);
debugPrint('🔴 HolePainter paint: 绘制调试边框完成');
}
@override
bool shouldRepaint(covariant _HolePainter oldDelegate) {
return oldDelegate.iconPosition != iconPosition ||
oldDelegate.iconSize != iconSize;
}
}