I am trying to add the qr_code_scanner to a flutter project.
What I need to do is to press a Scan button on the MainPage
, open the QRScanner
page and then pass the result back to the MainPage
in a TextEditingController
.
I managed to do all that. However, when I pass the QR Scan result back to the MainPage
I am replacing the entire MainPage
context. I am also resetting the values for all other controllers.
So once I finally do Navigator.pop(context);
I am redirected back to the QRScanner
, page instead of the Dashboard, which is what I need to do.
My question is, how can I pass the QR Scan result back without replacing the MainPage
context? (At least I think this is the problem).
Main Page:
class MainPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => new _MainPageState();
}
class _MainPageState extends State<MainPage> {
late Store<AppState> store;
final TextEditingController _name = new TextEditingController();
late final TextEditingController _qrText = new TextEditingController();
late QRScan? args;
@override
initState() {
super.initState();
//In order to use the ModalRoute.of(context)?.settings.arguments outside build method
final widgetsBinding = WidgetsBinding.instance;
widgetsBinding.addPostFrameCallback((callback) async {
if (ModalRoute.of(context)?.settings.arguments != null) {
args = ModalRoute.of(context)!.settings.arguments as QRScan?;
_qrText.text = args!.result!;
}
});
}
void nextButton() async {
String name = _name.text;
String uniqueId = _qrText.text;
final response = await http.get(Uri.parse('url' ));
if (response.statusCode == 200) {
//Do something
Navigator.pop(context); //Here I get redirected back to /qrScanner Page instead of the Dashboard
} else {
//Throw error message
}
}
@override
Widget build(BuildContext context) {
return StoreConnector<AppState, StoreModel>(
onInit: (str) => str.dispatch({ store = str, }),
converter: (Store<AppState> store) => StoreModel.create(store),
builder: (BuildContext context, StoreModel storeModel) => SafeArea(
child: Scaffold(
appBar: new AppBar(),
body: new Container(
child: ListView(shrinkWrap: true, children: <Widget>[
new Column(
children: <Widget>[
_buildTextFields()
],
)
])),
)));
}
Widget _buildTextFields() {
return new Container(
child: new Column(
children: <Widget>[
new TextField(
controller: _name,
),
new TextField(
controller: _qrText,
),
ElevatedButton(
onPressed: () {
Navigator.pushNamed(context, "/qrScanner");
},
child: Text('Scan'),
),
ElevatedButton(
onPressed: () {
nextButton(); //Here I get redirected back to QR Scan page instead of dashboard
},
child: Text('Insert'),
)
],
),
);
}
}
QR Scan Page:
class QRScanner extends StatefulWidget {
const QRScanner({ Key ? key, }) : super(key: key);
@override
State<StatefulWidget> createState() => _QRScannerState();
}
class _QRScannerState extends State<QRScanner> {
Barcode? result;
QRViewController? controller;
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
@override
void reassemble() {
super.reassemble();
if (Platform.isAndroid) {
controller!.pauseCamera();
}
controller!.resumeCamera();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Expanded(flex: 4, child: _buildQrView(context)),
],
),
);
}
Widget _buildQrView(BuildContext context) {
return QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
);
}
void _onQRViewCreated(QRViewController controller) {
setState(() {
this.controller = controller;
});
controller.scannedDataStream.listen((scanData) {
setState(() {
result = scanData;
controller.pauseCamera();
controller.resumeCamera();
passToPreviousPage();
});
});
}
passToPreviousPage() {
controller?.pauseCamera();
Navigator.pushNamed(context, "/mainPage",
arguments: QRScan(result!.code));
}
@override
void dispose() {
controller!.dispose();
super.dispose();
}
}
class QRScan {
final String? result;
QRScan(this.result);
}
You can push a route and use await
to get the results. Then from the pushed page you can return the result with Navigator.of(context).pop()
.
To do so, use this code when you push the route where you scan the QR code:
onPressed: () async {
final qrCode = await Navigator.pushNamed(context, "/qrScanner");
},
Then in the page where you scan the QR code, return the scanned code with:
Navigator.of(context).pop(result!.code);
You can also set the type that will be returned by the route:
final qrCode = await Navigator.pushNamed<Your_Type_Here>(context, "/qrScanner");