I'd like to create a transparent mask on top of a live camera feed that looks like this:
The idea I had is to stack a Container
on top of the CameraPreview
like so:
Stack(
alignment: Alignment.center,
children: [
// Camera feed first
CameraPreview(controller!),
// With a shaded container on top
Container(
color: Colors.black.withOpacity(.7),
child: Center(
// And a hole in the center for the transparent frame
child: Container(
width: 200,
height: 100,
color: Colors.transparent,
),
),
),
],
)
Instead of getting the desired output above, I get this:
I mean, I can see what Flutter's thinking here -- transparent means it'll show the Container
background underneath, not cut a hole in the container.
But how do I get the output I desire?
CodePudding user response:
Your Approach is correct of using layers, But our main focus is to clip out the needed section and keep the other overlay as it is. So
Layer Implementation would be like this:
Stack(
alignment: Alignment.center,
children: [
// Camera feed first
CameraPreview(controller!),
//would be the Overlay Widget
OverlayWithRectangleClipping()
],
)
A Separate widget is used or I can say a screen for some additional options you can just use the widget as well. The job has been carried out using Custom Painter. Later OverlayWithRectangleClipping would look like this:
class OverlayWithRectangleClipping extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.transparent,
body: _getCustomPaintOverlay(context));
}
//CustomPainter that helps us in doing this
CustomPaint _getCustomPaintOverlay(BuildContext context) {
return CustomPaint(
size: MediaQuery.of(context).size, painter: RectanglePainter());
}
}
class RectanglePainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()..color = Colors.black54;
canvas.drawPath(
Path.combine(
PathOperation.difference, //simple difference of following operations
//bellow draws a rectangle of full screen (parent) size
Path()..addRect(Rect.fromLTWH(0, 0, size.width, size.height)),
//bellow clips out the circular rectangle with center as offset and dimensions you need to set
Path()
..addRRect(RRect.fromRectAndRadius(
Rect.fromCenter(
center: Offset(size.width * 0.5, size.height * 0.5),
width: size.width * 0.85,
height: size.height * 0.3),
Radius.circular(15)))
..close(),
),
paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
Note: Above can be implemented in many ways like the one mentioned in the comments and optimizations can be done above will get you your desired result.
CodePudding user response:
you can use "CustomPaint" in the flutter. some inspiration from image_crop