Please help me create a flutter camera app with a mask layout. I do not know how to make the camera have a rectangular mask that automatically frames the image after shooting.
At the moment, I'm making an image and then manually cropping it, after which it is saved in the gallery.
The code looks like this
Main.dart
import 'dart:io';
import 'package:app_math_img/services/image_picker_service.dart';
import 'package:flutter/material.dart';
import 'package:image_cropper/image_cropper.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:image_picker/image_picker.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({super.key, required this.title});
final String title;
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@override
State<MyHomePage> createState() => _MyHomePageState(_scaffoldKey);
}
class _MyHomePageState extends State<MyHomePage> {
final GlobalKey<ScaffoldState> _scaffoldKey;
_MyHomePageState(this._scaffoldKey);
XFile? imageFile;
Future<void> saveImageToGallery() async {
// Save image to gallery
await ImageGallerySaver.saveFile(imageFile!.path);
// Show a message to the user
if (_scaffoldKey.currentContext != null) {
ScaffoldMessenger.of(_scaffoldKey.currentContext!).showSnackBar(
const SnackBar(
content: Text('Image saved to Gallery'),
),
);
}
// Trigger a rebuild to display the saved image
setState(() {});
}
void _onClick() async {
imageFile = await ImagePickerService().pickCropImage(
cropAspectRatio: const CropAspectRatio(ratioX: 16, ratioY: 9),
imageSource: ImageSource.camera,
);
if (imageFile != null) {
saveImageToGallery();
}
setState(() => {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: widget._scaffoldKey,
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: imageFile != null
? Image(image: FileImage(File(imageFile!.path)))
: const Text('No image selected'),
),
floatingActionButton: FloatingActionButton(
onPressed: _onClick,
child: const Icon(Icons.camera),
),
);
}
}
image_picker_service.dart
import 'package:image_cropper/image_cropper.dart';
import 'package:image_picker/image_picker.dart';
class ImagePickerService {
Future<XFile?> pickCropImage({
required CropAspectRatio cropAspectRatio,
required ImageSource imageSource,
}) async {
//Pick image
XFile? pickImage = await ImagePicker().pickImage(source: imageSource);
if (pickImage == null) return null;
//Crop picked image
CroppedFile? croppedFile = await ImageCropper().cropImage(
sourcePath: pickImage.path,
aspectRatio: cropAspectRatio,
compressQuality: 90,
compressFormat: ImageCompressFormat.jpg,
);
if (croppedFile == null) return null;
return XFile(croppedFile.path);
}
}