Files
ai_chat_assistant/lib/widgets/_hole_overlay.dart

80 lines
2.0 KiB
Dart
Raw 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/gestures.dart';
/// 遮罩层icon 区域挖洞可交互
class HoleOverlay extends StatelessWidget {
final Offset iconPosition;
final double iconSize;
final VoidCallback? onTap;
const HoleOverlay({
super.key,
required this.iconPosition,
required this.iconSize,
this.onTap,
});
@override
Widget build(BuildContext context) {
return Listener(
behavior: HitTestBehavior.translucent,
onPointerDown: (PointerDownEvent event) {
final RenderBox box = context.findRenderObject() as RenderBox;
final Offset local = box.globalToLocal(event.position);
final iconRect = Rect.fromLTWH(
iconPosition.dx,
iconPosition.dy,
iconSize,
iconSize,
);
if (!iconRect.contains(local)) {
// 遮罩区域,拦截并关闭弹窗
if (onTap != null) {
onTap!();
}
}
// 如果点在icon区域什么都不做事件会传递到下层
},
child: CustomPaint(
size: Size.infinite,
painter: _HolePainter(
iconPosition: iconPosition,
iconSize: iconSize,
),
),
);
}
}
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 paint = Paint()
..color = Colors.white.withOpacity(0.0)
..blendMode = BlendMode.srcOver;
// 画全屏遮罩
canvas.drawRect(Offset.zero & size, paint);
// 挖洞
final holeRect = Rect.fromLTWH(
iconPosition.dx,
iconPosition.dy,
iconSize,
iconSize,
);
final holePath = Path()..addOval(holeRect);
paint.blendMode = BlendMode.clear;
canvas.drawPath(holePath, paint);
}
@override
bool shouldRepaint(covariant _HolePainter oldDelegate) {
return iconPosition != oldDelegate.iconPosition || iconSize != oldDelegate.iconSize;
}
}