Document Frame Scanner
The DocumentFrameScanner
package streamlines the process of scanning documents with a flexible camera interface designed for capturing and trimming document images. It's perfect for apps needing quick and intuitive document scanning solutions.
Features
- Document Frame: Adjustable frame size for precise document scanning.
- Camera Preview: Live camera feed offering real-time visual feedback.
- Intuitive Controls:
- Capture: Snap a photo of the document.
- Save: Store the scanned image.
- Retake: Retake if the result isn’t satisfactory.
- Customizable Interface:
- Set frame dimensions, button designs, and placement.
- Include optional titles with customizable alignment and spacing.
- Event Listeners: Effortlessly manage actions like
onCaptured
,onSaved
, andonRetake
.
Installation
Add the package to your Flutter project using:
flutter pub add document_frame_scanner
Then run:
flutter pub get
Setup
iOS Setup
Add the following keys to your ios/Runner/Info.plist
file to request camera and microphone
permissions:
<plist version="1.0">
<dict>
<!-- Add the following keys inside the <dict> section -->
<key>NSCameraUsageDescription</key>
<string>We need camera access to capture documents.</string>
<key>NSMicrophoneUsageDescription</key>
<string>We need microphone access for audio-related features.</string>
</dict>
</plist>
Android Setup
- Update the
minSdkVersion
to 21 or higher inandroid/app/build.gradle
:
android {
defaultConfig {
minSdk 21
}
}
- Add these permissions to your
AndroidManifest.xml
file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<application android:label="MyApp" android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<!-- Activities and other components -->
</application>
</manifest>
Managing Camera Access Permissions
When initializing the camera, you might encounter permission-related errors that need to be handled appropriately. Below is a list of potential error codes and their meanings:
Error Code | Meaning |
---|---|
CameraAccessDenied |
The user has denied permission to access the camera. |
CameraAccessDeniedWithoutPrompt |
iOS only: The user previously denied camera access and must manually enable it in Settings. |
CameraAccessRestricted |
iOS only: Camera access is restricted, such as through parental controls. |
AudioAccessDenied |
The user has denied permission to access the microphone. |
AudioAccessDeniedWithoutPrompt |
iOS only: The user previously denied microphone access and must manually enable it in Settings. |
AudioAccessRestricted |
iOS only: Microphone access is restricted, such as through parental controls. |
Usage
Import the Package
import 'package:document_frame_scanner/document_frame_scanner.dart';
Example
import 'package:document_frame_scanner/document_frame_scanner.dart';
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(title: const Text('Document Frame Scanner')),
body: Center(
child: ElevatedButton(
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(builder: (_) => const DocumentFrameScannerExample()),
),
child: const Text('Start Document Capture'),
),
),
),
);
}
}
class DocumentFrameScannerExample extends StatelessWidget {
const DocumentFrameScannerExample({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: DocumentFrameScanner(
frameWidth: 300.0,
frameHeight: 200.0,
title: const Text(
'Capture Your Document',
style: TextStyle(color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold),
),
showCloseButton: true,
onCaptured: (imgPath) => debugPrint('Captured image path: $imgPath'),
onSaved: (imgPath) => debugPrint('Saved image path: $imgPath'),
onRetake: () => debugPrint('Retake button pressed'),
),
);
}
}
Widget Parameters
Parameter | Type | Description | Required | Default Value |
---|---|---|---|---|
frameWidth |
double |
Width of the document capture frame. | ✅ | — |
frameHeight |
double |
Height of the document capture frame. | ✅ | — |
title |
Widget? |
Optional widget to display as the screen title. | ❌ | null |
screenTitleAlignment |
Alignment? |
Alignment of the screen title. | ❌ | Alignment.topCenter |
screenTitlePadding |
EdgeInsets? |
Padding for the screen title. | ❌ | EdgeInsets.zero |
captureButtonText |
String? |
Text for the "Capture" button. | ❌ | "Capture" |
captureButtonTextStyle |
TextStyle? |
Text style for the "Capture" button. | ❌ | null |
captureButtonStyle |
ButtonStyle? |
Style for the "Capture" button. | ❌ | null |
captureButtonAlignment |
Alignment? |
Alignment of the "Capture" button. | ❌ | Alignment.bottomCenter |
captureButtonPadding |
EdgeInsets? |
Padding for the "Capture" button. | ❌ | null |
onCaptured |
Function(String) |
Callback triggered when an image is captured. | ✅ | — |
saveButtonText |
String? |
Text for the "Save" button. | ❌ | "Save" |
saveButtonStyle |
ButtonStyle? |
Style for the "Save" button. | ❌ | null |
saveButtonAlignment |
Alignment? |
Alignment of the "Save" button. | ❌ | Alignment.bottomRight |
onSaved |
Function(String) |
Callback triggered when an image is saved. | ✅ | — |
retakeButtonText |
String? |
Text for the "Retake" button. | ❌ | "Retake" |
retakeButtonStyle |
ButtonStyle? |
Style for the "Retake" button. | ❌ | null |
onRetake |
VoidCallback? |
Callback triggered when the "Retake" button is pressed. | ❌ | null |
frameBorder |
BoxBorder? |
Border for the displayed frame. | ❌ | null |
capturingAnimationDuration |
Duration? |
Duration of the capturing animation. | ❌ | Duration(milliseconds: 1000) |
capturingAnimationColor |
Color? |
Color of the capturing animation. | ❌ | Colors.black26 |
capturingAnimationCurve |
Curve? |
Curve for the capturing animation. | ❌ | Curves.easeInOut |
outerFrameBorderRadius |
double |
Radius for the outer frame's border. | ❌ | 12.0 |
innerCornerBroderRadius |
double |
Radius for the inner corners of the frame. | ❌ | 8.0 |
animatedFrameDuration |
Duration |
Duration for the frame animation. | ❌ | Duration(milliseconds: 400) |
animatedFrameCurve |
Curve |
Curve for the frame animation. | ❌ | Curves.easeIn |
bottomFrameContainerChild |
Widget? |
Custom widget for the bottom container. | ❌ | null |
showCloseButton |
bool |
Whether to show a Close button. | ❌ | false |
License
This project is licensed under the MIT License. See the LICENSE file for details.