0

In my Flutter app I want to scan some barcodes. After scanning the barcode I want to show a snackbar. The app should run on an Android device.

Unfortunately the snackbar never shows up. Both functionalities (barcode scanning and showing the snackbar) work fine separately.

During debugging, following happens:

  1. The camera opens
  2. The barcode is scanned
  3. The barcode is stored in the variable
  4. The screen turns black
  5. The code for the snack bar is executed. The snack bar is not displayed.
  6. After leaving the method the view/widget on which the snack bar is to be shownn is rendered again.

The barcode scanning is handled by the flutter plugin barcode_scan in version 0.0.3.

Here is the matching code:

final GlobalKey<ScaffoldState> keyScaffold = new GlobalKey<ScaffoldState>();

[...]

@override
Widget build(BuildContext context) {
  return new Scaffold(
    key: keyScaffold,
    [...]
}

Future scan() async {
  String snackBarMessage = "No error";

  try {
    String barcode = await BarcodeScanner.scan();
    setState(() => _barcodeController.text = barcode);
    snackBarMessage = barcode;
  } on PlatformException catch (e) {
    if (e.code == BarcodeScanner.CameraAccessDenied) {
      snackBarMessage = 'The user did not grant the camera permission!';
    } else {
      snackBarMessage = 'Unknown error: $e';
    }
  } on FormatException {
    snackBarMessage =
        'null (User returned using the "back"-button before scanning anything. Result)';
  } catch (e) {
    snackBarMessage = 'Unknown error: $e';
  }

  keyScaffold.currentState.showSnackBar(new SnackBar(
    content: new Text(snackBarMessage),
    duration: new Duration(seconds: 5),
  ));
}
Moltie
  • 1
  • 3

1 Answers1

0

On my prototype flutter app (flutter ver. 0.5.1 beta), I use both the snackbar and the barcode_scan plugin (ver. 0.0.4) and the snackbar DOES show up (with the result of the scan as a string). All credits go to Wahib Ul Haq for easier snackbar editing:

Display SnackBar in Flutter

In my case, there are 2 things worth noticing.

  1. I don't use keyScaffold at all. I declare a BuildContext as a variable (I call it scaffoldContext) to hold the body of the Scaffold.

  2. I declare and initialise a new Scaffold. For its body, I write a Builder. Inside the builder, I initialize scaffoldContext as context for the Builder.

Here's my code for easier understanding:

import 'package:flutter/material.dart';
import 'package:barcode_scan/barcode_scan.dart';
import 'package:flutter/services.dart';
[...]

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      [...],
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {  
  //This is what I meant in note #1.
  BuildContext scaffoldContext;

  String barcode;

  @override
  initState() {
    super.initState();
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('MyApp'),
      ),
      //This is what I meant in note #2.
      body: Builder(builder: (BuildContext context) {
        scaffoldContext = context;
        return Center(
            child: Column(children: <Widget>[
              ListTile(
              [...]
              ),
              ListTile(
              [...]
              ),
              [...]
            ]

    ));}),

      floatingActionButton: FloatingActionButton(
        mini: true,
        child: Icon(Icons.crop_free), onPressed: fabPressed),
    )};

  void createSnackBar(String message) {
    final snackBar = new SnackBar(content: new Text(message),
        backgroundColor: Colors.black

    );

    Scaffold.of(scaffoldContext).showSnackBar(snackBar);
  }

  void fabPressed() async {
    barcode = "";

    try {
    barcode = await BarcodeScanner.scan();
    setState(() => this.barcode = barcode);

    createSnackBar(barcode);
    }
    on PlatformException catch (e) {
      if (e.code == BarcodeScanner.CameraAccessDenied) {
        setState(() {
          this.barcode = 'The user did not grant the camera permission!';
        });
        } else {
          setState(() => this.barcode = 'Unknown error: $e');
      }
    }
    on FormatException {
      setState(() =>
  this.barcode = 'null (User returned using the "back"-button before scanning anything. Result)');
    }
    catch (e) {
      setState(() => this.barcode = 'Unknown error: $e');
    }
  }
}