Flutter:如何检测自定义绘制覆盖后屏幕是否完全变白?
问题:检测白色绘制是否完全覆盖初始背景
我在谷歌搜索后,找到的都是从Image中获取颜色像素的方案,这与我的场景不同,这类问题可使用image_pixels插件解决,但这不是我的需求。
我正在开发一个页面,用户可通过手指完成小游戏:擦除屏幕内容,当屏幕完全变为白色时完成测试,本质是覆盖当前页面的所有颜色。
我的问题是不知道如何检测用户绘制的白色是否完全覆盖初始背景。我在谷歌找到一个类似的旧帖子,但无人解答,不确定是否可行。
我尝试过创建橡皮擦对象,但遇到BlendMode.clear无法生效的问题,且我不想通过Offset位置获取像素颜色,而是希望编写条件判断整个页面是否完全变白。
CustomPainter代码
class ScreenCheckPainter extends CustomPainter { final List<Sketch> points; ScreenCheckPainter({required this.points}); @override void paint(Canvas canvas, Size size) { Paint paint = Paint() ..strokeCap = StrokeCap.round ..strokeWidth = 65.0 ..style = PaintingStyle.stroke; canvas.saveLayer(Rect.largest, Paint()); for (Sketch sketch in points) { final point = sketch.points; final path = Path(); path.moveTo(point.first.dx, point.first.dy); for (int i = 0; i < point.length - 1; ++i) { final p0 = point[i]; final p1 = point[i + 1]; path.quadraticBezierTo( p0.dx, p0.dy, (p0.dx + p1.dx) / 2, (p0.dy + p1.dy) / 2, ); canvas.drawCircle(point[i], 10, paint..color = Colors.white); } canvas.drawPath(path, paint..color = Colors.white); } canvas.restore(); } @override bool shouldRepaint(ScreenCheckPainter oldDelegate) { return oldDelegate.points != points; } }
UI代码
class ScreenCheckPage extends ConsumerStatefulWidget { const ScreenCheckPage({super.key}); @override ConsumerState<ConsumerStatefulWidget> createState() => _ScreenCheckPageState(); } class _ScreenCheckPageState extends ConsumerState<ScreenCheckPage> { final List<Offset> points = <Offset>[]; Offset localPos = const Offset(-1, -1); @override Widget build( BuildContext context, ) { Widget buildCurrentPath(BuildContext context, GetSketch currentSketch, GetSketchList currentListSketch) { int _pointers = 0; var countdown = ref.watch(testCountdownProvider); return GestureDetector( onPanDown: (details) { final box = context.findRenderObject() as RenderBox; final offset = box.globalToLocal(details.localPosition); setState( () { localPos = details.localPosition; currentSketch.updateCurrentSketch(Sketch(points: [offset])); _pointers++; }, ); //debugPrint(currentSketch.currentSketch.toString()); }, onPanUpdate: (details) { final box = context.findRenderObject() as RenderBox; final offset = box.globalToLocal(details.localPosition); final points = List<Offset>.from(ref.read(getSketchProvider)?.points ?? []) ..add(offset); setState( () { localPos = details.localPosition; currentSketch.updateCurrentSketch(Sketch(points: points)); _pointers--; }, ); //debugPrint(currentSketch.currentSketch.toString()); }, onPanEnd: (details) { setState( () { currentListSketch .updateCurrentListSketch(ref.read(getSketchProvider)!); }, ); }, child: IgnorePointer( ignoring: _pointers > 1, child: _pointers > 1 ? null : SizedBox( height: MediaQuery.of(context).size.height, width: MediaQuery.of(context).size.width, child: CustomPaint( isComplex: true, willChange: true, painter: ScreenCheckPainter( points: ref.read(getSketchProvider) == null ? [] : [ref.read(getSketchProvider)!], ), child: Container( alignment: Alignment.bottomCenter, margin: const EdgeInsets.only(bottom: 50), ), ), ), ), ); } Widget buildAllPath(BuildContext context, GetSketchList currentListSketch) { return SizedBox( height: MediaQuery.of(context).size.height, width: MediaQuery.of(context).size.width, child: CustomPaint( foregroundPainter: ScreenCheckPainter( points: ref.read(getSketchListProvider), ), ), ); } final GetSketch currentSketch = ref.watch(getSketchProvider.notifier); final GetSketchList currentListSketch = ref.watch(getSketchListProvider.notifier); return RepaintBoundary( child: Stack( children: [ const Image( image: AssetImage("assets/design/ambercolor.png"), fit: BoxFit.cover, height: double.infinity, width: double.infinity, alignment: Alignment.center, ), buildAllPath(context, currentListSketch), buildCurrentPath(context, currentSketch, currentListSketch), ], ), ); } }
Riverpod状态代码
@riverpod class GetSketch extends _$GetSketch { Sketch? _currentSketch; Sketch? get currentSketch => _currentSketch; @override Sketch? build() { return currentSketch; } void updateCurrentSketch(Sketch newSketchPos) { state = newSketchPos; } Sketch? getCurrentSketch() { return state; } } @riverpod class GetSketchList extends _$GetSketchList { final List<Sketch> _currentListSketch = []; List<Sketch> get currentListSketch => _currentListSketch; @override List<Sketch> build() { return currentListSketch; } void updateCurrentListSketch(Sketch newSketchData) { state = [...state, newSketchData]; } List<Sketch> getListOfSketch() { return state; } }
Model代码
class Sketch { final List<Offset> points; Sketch({required this.points}); }
内容的提问来源于stack exchange,提问作者Jirayuth Porka
相关产品推荐
相关产品推荐

