I have an emoji-selector that works perfectly, but I would like to parse the emoji selected to TextField in Flutter. Below I have below my TextField and Emoji Selector.
Widget buildSticker() {
return EmojiPicker(
rows: 10,
columns: 5,
buttonMode: ButtonMode.MATERIAL,
recommendKeywords: ["racing", "horse","Face","Ghost"],
numRecommended: 10,
onEmojiSelected: (emoji, category) {
print(emoji);
},
);
}
I want the emoji picker to display on the TextField below:
TextField(
controller: _controllerComment,
keyboardType: TextInputType.multiline,
maxLines: null,
),
My emoji return it print as : Upside-Down Face, Emoji: 🙃
Add emoji into _controllerComment like this using emoji_picker_flutter,
onEmojiSelected: (category, emoji) {
setState(() {
_controllerComment.text = _controllerComment.text + emoji.emoji;
});
},
Related
I have implemented TextField with FilteringTextInputFormatter as below to allow enter only alphanumeric characters. But at the same time I want to display error message if user tap on a denied character. Is is possible with FilteringTextInputFormatter?
I know its possible to just display error message with a simple regex validation, But I want both FilteringTextInputFormatter and error message together.
static final _alphaNumericCharacters = RegExp('[0-9a-zA-Z]');
TextField(
controller: _myController,
onChanged: provider.onChanged,
decoration: InputDecorations.buildErrorInputDecoration(
hintText:
'Please enter your ID',
setError: isInputError,
errorText:
'Only alphanumeric characters are allowed'),
keyboardType: TextInputType.text,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(_alphaNumericCharacters),
],
),
Define a bool value for checking input value.
bool checkDigit = true;
In TextFormField,
TextFormField(
decoration: InputDecoration(
errorText: checkDigit == false
? "You can write only numeric values"
: ""),
keyboardType: TextInputType.text,
onChanged: (value) {
if (!_isNumeric(value)) {
setState(() {
checkDigit = false;
});
} else {
setState(() {
checkDigit = true;
});
}
},
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(_alphaNumericCharacters),
],
),
isNumeric function detects parameter is a number or not. If the given value is number, return true otherwise false.
bool _isNumeric(String result) {
return double.tryParse(result) != null;
}
You can custom TextInputFormatter like this
class Decimal extends TextInputFormatter {
final Function(bool) onError;
Decimal({this.onError});
#override
TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
// allow only one of common decimal separator
bool match = RegExp(r'^[0-9]+([.,])+[0-9]+$').hasMatch(newValue.text);
onError(match);
return newValue;
}
}
Your text input should look like:
TextField(
...
errorText: _isError ? 'error' : null,
inputFormatters: [
Decimal(
onError: (match){
setState((){
// if not match, error is true, otherwise
_isError= !match;
});
}),
],
)
Worked in my case, only allow for valid decimal format. You can give it a try to custom for your own TextInputFormatter.
I am using Flutter Multiselect from official - flutter_multiselect: ^0.5.1
everything works fine , but onSaved() event not fired after selecting/deselecting and clicking the save button in MultiSelect Widget. i just wanna print the selected/deselected item in console.
Note : am also trying to get via change() event , its works only if we selecting the option, not works while deselcting.
help me to resolve this problem
Sample Code:
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
),
alignment: Alignment.center,
child: new MultiSelect(
maxLength: 1,
maxLengthText: "",
autovalidate: false,
dataSource: countries,
textField: 'country_name',
valueField: 'country_id',
hintText: "Select Your Country",
initialValue: countryID,
value: countryID,
required: true,
validator: (value) {
if (value == null) {
return 'Please Select Country';
}
},
filterable: true,
change: (values) {
if (values != null) {
setState(() {
countryID = values.cast<String>();
getStatesByCountry();
});
}
//this event emitted while selecting option from multiselect
//not works on deselecting option from multiselect
},
onSaved: (value) {
debugPrint("on save event");
print(value);
//always not emitting
},
),
)
Since I cannot see whole code, it's hard to tell but I would guess you don't save the whole form like this:
void _onFormSaved() {
final FormState form = _formKey.currentState;
form.save();
}
I would recommend to follow this original example
Hope it somehow help. Cheers
i dont know its a correct way, but in my case just cleaned a build and reinstalled packge will emit onchange event while removing items in multiselect,nothing else works me
How can I open keyboard type == emoji. Not number, not letter, just emoji. Without using emoji_picker package
To open the emoji container emoji_picker
Create A method emojiContainer
emojiContainer() {
return EmojiPicker(
bgColor: Colors.red,
indicatorColor: Colors.blue,
rows: 3,
columns: 7,
onEmojiSelected: (emoji, category) {
setState(() {
isWriting = true;
});
textFieldController.text = textFieldController.text + emoji.emoji;
},
recommendKeywords: ["face", "happy", "party", "sad"],
numRecommended: 50,
);
}
And use an onPressed
onPressed: () {
if (!showEmojiPicker) {
// keyboard is visible
hideKeyboard();
showEmojiContainer();
} else {
//keyboard is hidden
showKeyboard();
hideEmojiContainer();
}
},
I added a speech recognition to a text field, it works but I cannot manage to add the text to the textfield, is there a way to do that.
the textfield looks like this:
Widget _buildDescriptionTextField(productBloc) {
return StreamBuilder<Object>(
stream: productBloc.messageStream,
builder: (context, snapshot) {
return TextField(
maxLines: 3,
controller: _controllerMessage,
onChanged: productBloc.messageSink,
decoration: InputDecoration(
labelText: allTranslations.text(StringConstant.description),
errorText: snapshot.error,
suffixIcon: IconButton(icon: Icon(Icons.mic), onPressed: () {
if (_isAvailable && !_isListening)
_speechRecognition
.listen(locale: "en_US")
.then((result) => print('$result'));
},
),
),
);
}
);
}
I have a steam-builder to manage the added text manually, and an controller if this page is used for editing, then as suffixsIcon the iconButton to start the speech recognition. when I add the result text outside a text Widget it works but I need it inside the texField.
Just doing that should work no ?
setState(() => _controllerMessage.text = result)
You need to use TextEditingController properties. I assume you declared one as _controllerMessage.
To set new value to your TextField and keep the cursor in the end - use something similar to the example from the Docs.
e.g.
_speechRecognition
.listen(locale: "en_US")
.then(_onResult);
// ...
void _onResult(String result) {
setState(() {
_controllerMessage.value = _controllerMessage.value.copyWith(
text: result,
selection: TextSelection(baseOffset: result.length, extentOffset: result.length),
composing: TextRange.empty,
);
});
}
Let me know if this helped.
So What I did is just used the _speechRecognition.setRecognitionResultHandler from the documentation, to set a new value to the controller of the textField, like so:
_speechRecognition.setRecognitionResultHandler(
(String speech) => setState(() {
_controllerMessage = new TextEditingController(text: resultText = speech);
})
);
the textField stays like it was before, see question.
In my case i need to scan barcode and fetch product details. Normally barcode scanner devices emit enter key(keycode=13) event at end of scanning, But in flutter enter key is not same as Done so how can code to detect enter key pressed in my TextFormField widget?
if you are using TextField then you have to add onSubmitted in your text field to detect when user press Enter key. For my case, I changed Done in keyboard to TextInputAction.Search. It also works for TextInputAction.Done too. here is a sample code
TextField(
onSubmitted: (value){
//value is entered text after ENTER press
//you can also call any function here or make setState() to assign value to other variable
},
textInputAction: TextInputAction.search,
)
The solution above works, but I believe RawKeyboardListener is a more reliable and flexible solution. You just need to cover the text field with it and start to listen to keyboard events:
var focusNode = FocusNode();
RawKeyboardListener(
focusNode: focusNode,
onKey: (event) {
if (event.isKeyPressed(LogicalKeyboardKey.enter)) {
// Do something
}
},
child: TextField(controller: TextEditingController())
)
As a second option you can use onKey method of the FocusNoded and pass the node to your text field:
var focusNode = FocusNode(onKey: (node, event) {
if (event.isKeyPressed(LogicalKeyboardKey.enter)) {
// Do something
// Next 2 line needed If you don't want to update the text field with new line.
// node.unfocus();
// return true;
}
return false;
});
TextField(focusNode: focusNode, controller: TextEditingController())
In case someone is looking for the same solution (as Al Walid Ashik) but for TextFormField, just use the following:
TextFormField(
/// ...
onFieldSubmitted: (value) {
/// do some stuff here
},
),
TextFormField(
maxLines: null,
autovalidate: true,
validator: (value){
if(value.contains('\n')){
doFun(value);
}
}
)
When user press enter key new line create in text box. We check with that.
maxLine:null - to hide multiline
autovalidate:true -to automatically run validator fun
'\n' - new line ('\s'-whitespace,'\t'-tab.. etc)
In addition to the Sergey Yamshchikov's answer:
In case if it is a multiline TextField (maxLines: null) and you want to catch up the entered key and prevent passing it into the text field, you can use this approach:
RawKeyboardListener(
focusNode: FocusNode(onKey: (node, event) {
if (event.isKeyPressed(LogicalKeyboardKey.enter)) {
return KeyEventResult.handled; // prevent passing the event into the TextField
}
return KeyEventResult.ignored; // pass the event to the TextField
}),
onKey: (event) {
if (event.isKeyPressed(LogicalKeyboardKey.enter)) {
// Do something
}
},
child: TextField(controller: TextEditingController())
)
But, if you need to detect the keys combination, like ctrl+enter, then you can use CallbackShortcuts:
CallbackShortcuts(
bindings: {
const SingleActivator(LogicalKeyboardKey.enter, control: true): _doSomething(),
},
child: Focus(
autofocus: true,
child: TextField(controller: TextEditingController()),
),
);