In this blog post, we will see Generate Dynamic Downloadable QR code for Flutter Web in 2024 using qr_flutter Package.

we’ll walk through a Flutter web application that generates a QR code dynamically based on user input and allows users to download the generated QR code as an image. We’ll use the qr_flutter library for generating QR codes and integrate HTML functionality for downloading the QR code image.

Prerequisites

Make sure you have the following dependencies in your pubspec.yaml file:

dependencies:
  flutter:
    sdk: flutter
  qr_flutter: ^4.0.0

Now, let’s dive into the code and understand how it works.

Overview

The Flutter web application consists of a simple user interface with a text input field to enter data and a button to trigger the QR code generation and download process. The QR code is generated using the qr_flutter library, and the image is downloaded using HTML functionality.

Setting Up the Flutter Web Application

Firstly, create a new Flutter web application and add the required dependencies. Replace the content of your lib/main.dart file with the provided code.

// Import necessary packages and libraries
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'dart:html' as html;
import 'dart:ui' as ui;

void main() {
  runApp(const MyApp());
}

// Define the main application widget
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Download QR Code Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Download QR Code Example'),
    );
  }
}

// Define the home page widget
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

Implementing QR Code Generation and Download

The _MyHomePageState class contains the logic for generating and downloading QR codes. The downloadQrCode function is called when the user clicks the “Download QR Code” button.

class _MyHomePageState extends State<MyHomePage> {
  final TextEditingController _textController = TextEditingController();

  void downloadQrCode() async {
    if (_textController.text.isNotEmpty) {
      final qrData = _textController.text;
      final qrPainter = QrPainter(
        data: qrData,
        version: QrVersions.auto,
        eyeStyle: const QrEyeStyle(color: Colors.white),
        dataModuleStyle: const QrDataModuleStyle(color: Colors.white),
      );

      final ui.Picture picture = qrPainter.toPicture(300);
      final ui.Image image = await picture.toImage(300, 300);
      final ByteData? byteData = await image.toByteData(format:ui.ImageByteFormat.png);

      final buffer = Uint8List.sublistView(byteData!.buffer.asUint8List());

      final blob = html.Blob([buffer]);
      final url = html.Url.createObjectUrlFromBlob(blob);
      final anchor = html.AnchorElement(href: url)
        ..target = 'blank'
        ..download = 'qrcode.png';
      html.document.body!.append(anchor);
      anchor.click();
      html.Url.revokeObjectUrl(url);
    } else {
      showDialog(
        context: context,
        builder: (context) {
          return AlertDialog(
            title: const Text('Error'),
            content: const Text('Please enter text to generate QR code'),
            actions: [
              TextButton(
                onPressed: () {
                  Navigator.of(context).pop();
                },
                child: const Text('OK'),
              ),
            ],
          );
        },
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    // Build the UI components here
  }
}

Building the User Interface

Now, let’s complete the build method to create the user interface with a text input field and a button.

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      title: Text(widget.title),
    ),
    body: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          SizedBox(
            width: 300,
            child: TextFormField(
              controller: _textController,
              decoration: const InputDecoration(
                labelText: 'Enter text to generate QR code',
                border: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(20))),
              ),
            ),
          ),
          const SizedBox(height: 20.0),
          TextButton(
            style: TextButton.styleFrom(
              foregroundColor: Theme.of(context).colorScheme.onPrimary,
              backgroundColor: Theme.of(context).colorScheme.primary,
            ),
            onPressed: downloadQrCode,
            child: const Text('Download QR Code'),
          ),
        ],
      ),
    ),
  );
}

Demo / Screenshot

YouTube Video Demo

Full Code

import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:qr_flutter/qr_flutter.dart';
// ignore: avoid_web_libraries_in_flutter
import 'dart:html' as html;
import 'dart:ui' as ui;

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Download QR Code Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Download QR Code Example'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final TextEditingController _textController = TextEditingController();
  void downloadQrCode() async {
    setState(() {});
    if (_textController.text.isNotEmpty) {
      final qrData = _textController.text;
      final qrPainter = QrPainter(
        data: qrData,
        version: QrVersions.auto,
        eyeStyle: const QrEyeStyle(color: Colors.white),
        dataModuleStyle: const QrDataModuleStyle(color: Colors.white),
      );

      final ui.Picture picture = qrPainter.toPicture(300);
      final ui.Image image = await picture.toImage(300, 300);
      final ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);

      final buffer = Uint8List.sublistView(byteData!.buffer.asUint8List());

      final blob = html.Blob([buffer]);
      final url = html.Url.createObjectUrlFromBlob(blob);
      final anchor = html.AnchorElement(href: url)
        ..target = 'blank'
        ..download = 'qrcode.png';
      html.document.body!.append(anchor);
      anchor.click();
      html.Url.revokeObjectUrl(url);
    } else {
      showDialog(
        context: context,
        builder: (context) {
          return AlertDialog(
            title: const Text('Error'),
            content: const Text('Please enter text to generate QR code'),
            actions: [
              TextButton(
                onPressed: () {
                  Navigator.of(context).pop();
                },
                child: const Text('OK'),
              ),
            ],
          );
        },
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            SizedBox(
              width: 300,
              child: TextFormField(
                controller: _textController,
                decoration: const InputDecoration(
                  labelText: 'Enter text to generate QR code',
                  border: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(20))),
                ),
              ),
            ),
            const SizedBox(height: 20.0),
            TextButton(
              style: TextButton.styleFrom(
                foregroundColor: Theme.of(context).colorScheme.onPrimary,
                backgroundColor: Theme.of(context).colorScheme.primary,
              ),
              onPressed: downloadQrCode,
              child: const Text('Download QR Code'),
            ),
          ],
        ),
      ),
    );
  }
}

Write A Comment

Pin It
Top Most Used Animation Widgets You Need to Know in 2024 Top 10+ Free Websites for Hosting for Beginners Developers Flutter AbsorbPointer class Use case in Depth 2023