I have a flutter app where I need to look up details after a barcode has been scanned into a TextFormField (using a physical Android mobile device). The scanner just sends the barcodes as keyboard input (with '\n' at the end).
I am using a RawKeyboardListener and it works fine when I manually enter text and press enter, however, the scanner sends the keystrokes at a much higher rate and the TextEditingController is still empty when the Enter key arrives at the RawKeyboardListener.
I am currently using a Future.delayed to wait 500 ms before trying to read the text and this works, but I do not like this solution very much (too fragile):
handleKey(RawKeyEvent event) {
var isEnter = event.logicalKey.keyId == LogicalKeyboardKey.enter.keyId || event.logicalKey.keyId == 1108101563381;
if (event.runtimeType.toString() == 'RawKeyDownEvent' && isEnter) {
print('- Text: ' + _textController.text); <--- Empty here
Future.delayed(const Duration(milliseconds: 500), () {
print('- Text after delay: ' + _textController.text); <--- '013803266986' here
});
}
}
My question: What is a more robust method to get the scanned barcode (text) after the Enter key?
Here is a full runnable sample:
import 'package:flutter/material.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() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController _textController = new TextEditingController();
FocusNode _textNode = new FocusNode();
handleKey(RawKeyEvent event) {
var isEnter = event.logicalKey.keyId == LogicalKeyboardKey.enter.keyId || event.logicalKey.keyId == 1108101563381;
if (event.runtimeType.toString() == 'RawKeyDownEvent' && isEnter) {
print('- Text: ' + _textController.text);
Future.delayed(const Duration(milliseconds: 500), () {
print('- Text after delay: ' + _textController.text);
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SizedBox(
width: double.infinity,
height: 300,
child: RawKeyboardListener(
focusNode: FocusNode(),
onKey: (event) => handleKey(event),
child: TextFormField(
controller: _textController,
focusNode: _textNode,
),
),
),
),
);
}
}
Note: This method does not work for me (since it makes the text field grow): Detect 'enter key' press in flutter