Introduction
QR codes remain a staple for secure data exchange in mobile development. Flutter’s ecosystem offers mature packages that simplify both generation and real-time scanning. This tutorial walks you through setting up dependencies, crafting QR code widgets, integrating a live camera scanner, and combining both features into a polished Flutter app. By the end, you will have a reusable component for generating styled QR images and scanning them with robust permission handling.
Setting Up Dependencies
First, add two packages to your pubspec.yaml:
• qr_flutter: Generates QR code widgets in Flutter.
• mobile_scanner: Provides a lightweight camera API for scanning.
Example pubspec.yaml excerpt:
dependencies:
flutter:
sdk: flutter
qr_flutter: ^4.0.0
mobile_scanner
Run flutter pub get to fetch these. In your Dart file, import:
import 'package:qr_flutter/qr_flutter.dart';
import 'package:mobile_scanner/mobile_scanner.dart';
Ensure your AndroidManifest.xml and Info.plist include camera permissions. On Android:
<uses-permission android:name="android.permission.CAMERA" />
On iOS, add a NSCameraUsageDescription in Info.plist.
Generating QR Codes
Use QrImage from qr_flutter to render a QR code on screen. It automatically encodes arbitrary data and supports customization via parameters:
Widget buildQrWidget(String data) {
return QrImage(
data: data,
version: QrVersions.auto,
size: 200.0,
gapless: false,
backgroundColor: Colors.white,
foregroundColor: Colors.indigo,
);
}Place this widget wherever you need a QR code. You can wrap it in GestureDetector to handle taps or long presses. Dynamically update the data property to generate new codes based on user input or API responses.
Scanning QR Codes
mobile_scanner makes it straightforward to embed a live camera feed that detects codes in real time. Create a MobileScannerController to manage the camera and torch:
class ScannerPage extends StatelessWidget {
final controller = MobileScannerController();
@override
Widget build(BuildContext context) {
return MobileScanner(
controller: controller,
onDetect: (barcode, args) {
final String code = barcode.rawValue ?? '---';
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('Scanned: $code')));
},
);
}
}You can toggle the torch or switch cameras by calling methods on the controller: controller.toggleTorch(), controller.switchCamera(). Wrap the scanner in a Scaffold or Stack to overlay UI elements like crosshairs or pause buttons.
Customizing and Integrating the Features
To build a cohesive interface, combine generation and scanning in a single screen. For example, use a TabBar with two tabs: “Generate” and “Scan.” In the Generate tab, include a TextField to capture user input, then rebuild the QrImage widget on submit. In the Scan tab, embed MobileScanner with an overlay to highlight detection zones.
Key customization tips:
• Styling: Adjust QrImage’s colors, size, and embedded logos via the embeddedImage and embeddedSize parameters. Ensure contrast for reliable scanning.
• Permissions: Check camera permission status at runtime with permission_handler or use MobileScannerController.cameraFacingState. Prompt users gracefully on denial.
• Performance: Pause the cameraController when switching tabs to conserve resources: controller.stop(); call controller.start(); on resume.
• Platform differences: Some Android devices require android:requestLegacyExternalStorage in manifest if you save scanned images; iOS requires permission strings in Info.plist.
Example integration snippet (pseudo-code):
TabBarView(
children: [
Column(children: [TextField(...), buildQrWidget(data)]),
ScannerPage(),
],
)
This approach centralizes QR logic, provides clear navigation, and maintains separation of concerns. Extract controllers and widgets into separate classes or providers to keep code maintainable.
Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.
Conclusion
Implementing QR code generation and scanning in Flutter is straightforward with qr_flutter and mobile_scanner. By structuring your app around reusable widgets and controllers, you can offer both functionalities in a single mobile development project. Proper permission handling, performance tuning, and UI customization ensure a professional-grade user experience. Use the patterns in this tutorial to integrate QR features into your next Flutter app, whether for ticketing, authentication, or data sharing.