Самый простой способ, который я нашел, это использовать ColorFiltered Widget с Stack .
Следующий код создаст именно то, что вы нужно:
@override
Widget build(BuildContext context) {
return Material(
child: Stack(
fit: StackFit.expand,
children: [
Image.network(
'https://wallpaperplay.com/walls/full/e/5/3/13586.jpg',
fit: BoxFit.cover,
),
ColorFiltered(
colorFilter: ColorFilter.mode(
Colors.black.withOpacity(0.8), BlendMode.srcOut), // This one will create the magic
child: Stack(
fit: StackFit.expand,
children: [
Container(
decoration: BoxDecoration(
color: Colors.black,
backgroundBlendMode: BlendMode.dstOut), // This one will handle background + difference out
),
Align(
alignment: Alignment.topCenter,
child: Container(
margin: const EdgeInsets.only(top: 80),
height: 200,
width: 200,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(100),
),
),
),
Center(
child: Text(
'Hello World',
style: TextStyle(fontSize: 70, fontWeight: FontWeight.w600),
),
)
],
),
),
],
),
);
}
Этот, который вы не только создаете "дыры" над видами, он работает с чем угодно! включая тексты и др. c.
Окончательный результат:
![Mask Out](https://i.stack.imgur.com/MgJyql.jpg)