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; } }