user13034054
user13034054

Reputation: 151

Flutter qr_code_scanner on successfully scanned data update navigation?

This is a widget, that have function that triggers each time we scan qr code.

  import 'package:qr_code_scanner/qr_code_scanner.dart';

 @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Column(
            children: <Widget>[
              Expanded(
                flex: 4,
                child: QRView(
                  key: qrKey,
                  onQRViewCreated: _onQRViewCreated,
                  overlay: QrScannerOverlayShape(
                    borderColor: Colors.red,
                    borderRadius: 10,
                    borderLength: 30,
                    borderWidth: 10,
                    cutOutSize: 300,
                  ),
                ),
              ),

In function I want to navigate to next screen.

  void _onQRViewCreated(QRViewController controller) {
    this.controller = controller;
    controller.scannedDataStream.listen((scanData) {
           Navigator.push(
           context,
          MaterialPageRoute(builder: (context) => SecondRoute()),
         );
    });
  }

Problem here is that that listen event trigger many times, is it possible to stop this function after first successfully scan data? I try with

controller.scannedDataStream.first;

But that return empty string and not triggers when real data are scanned.

I need to click 40 times to go back from Second Route to return to QR scanner widget. Thanks!

Upvotes: 7

Views: 9963

Answers (4)

Gowsik Raja
Gowsik Raja

Reputation: 732

I've faced the same issue, With lot of trial and error, found the solution qrViewController.dispose(). It's below.

onQRViewCreated: (QRViewController qrViewController) {
    this.qrViewController = qrViewController;
    qrViewController.scannedDataStream.listen((qrData) {
    final String qrCode = qrData.code;
      qrViewController.dispose();
      
      Navigator.push(
          context,
          MaterialPageRoute(
              builder: (context) => SecondPage(
                    qrCode: '$qrCode',
                  ))).then((value) => qrViewController.resumeCamera());
    });
  }

Upvotes: 1

Timur Dyushaliev
Timur Dyushaliev

Reputation: 111

If someone still has this problem, try this solution:) It works well for me!

onQRViewCreated: (QRViewController qrViewController) {
        this.qrViewController = qrViewController;
        qrViewController.scannedDataStream.listen((qrData) {
          qrViewController.pauseCamera();
          final String qrCode = qrData.code;
          Navigator.push(
              context,
              MaterialPageRoute(
                  builder: (context) => SecondPage(
                        qrCode: '$qrCode',
                      ))).then((value) => qrViewController.resumeCamera());
        });
      }

Upvotes: 7

Kurtus
Kurtus

Reputation: 81

for future reference i found pausing the camera works better :)

void _onQRViewCreated(QRViewController controller) {
this.controller = controller;
controller.scannedDataStream.listen((scanData) {
    qrText = scanData;
    SecondPageRoute();
   });
 }


SecondPageRoute() async {
       controller?.pauseCamera();
       var value = await Navigator.push(context,
           MaterialPageRoute(builder: (context) {
             return SecondPage(qrText);
           })).then((value) => controller.resumeCamera());
}

Upvotes: 8

Mohamed Abdou
Mohamed Abdou

Reputation: 451

You can just add a sentinel

void _onQRViewCreated(QRViewController controller) {
    this.controller = controller;
    bool scanned = false;
    controller.scannedDataStream.listen((scanData) {
      if (!scanned) {
        scanned = true;
        Navigator.push(
          context,
          MaterialPageRoute(builder: (context) => SecondRoute()),
        );
      }
    });
  }

Upvotes: 5

Related Questions