I am using speech to text (speech_recognition ) plugin and retrieving text from voice but how can i put the text in to the search field (TextField) after retrieving text. So i want to retrieve data from voice and search it.
here is my code:
// Here is retrieved text inside container
Container(
child: Center(
child: Text(
(transcription.isEmpty)
? "Speak to Record"
: "Your text is \n\n$transcription",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.pink, fontSize: 20),
),
),
),
// Here is my SearchField (TextField)
Padding(
padding: const EdgeInsets.all(20),
child: TextField(
onChanged: (text) {
_con.refreshSearch(text);
},
onSubmitted: (text) {
_con.saveSearch(text);
},
controller: _searchController,
autofocus: true,
decoration: InputDecoration(
contentPadding: EdgeInsets.all(12),
hintText: S.of(context).search_for_product,
hintStyle: Theme.of(context)
.textTheme
.caption
.merge(TextStyle(fontSize: 14)),
prefixIcon:
Icon(Icons.search, color: Theme.of(context).accentColor),
border: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).focusColor.withOpacity(0.1))),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).focusColor.withOpacity(0.3))),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Theme.of(context).focusColor.withOpacity(0.1))),
suffixIcon: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
children: [
InkWell(
onTap: scanBarcode,
child: Image.asset(
"assets/img/barcode.png",
height: 20,
color: Colors.deepOrangeAccent,
),
),
_buildVoiceInput(
onPressed: _speechRecognitionAvailable && !_isListening
? () => start()
: () => stop(),
label: _isListening ? S.of(context).listening : '',
),
],
),
),
),
),
Taking the transcription value into consideration, which is responsible of having the text, what you can do is to make use of it, and change the data using Search TextEditingController.
So, here what I am taking about. I am not sure where are you fetching the data actually, but you can change the values, as soon as you get the data from the voice like this, and assign it to the Controller to fill the Search Field
// Suppose you are fetching the data from this method,
void fetchTextFromVoice(){
setState(() {
// Here you might be assigning the value to the Transcript value
this.transcription = data_from_voice;
// also this does the magic, which will put the data inside the Search Field
// Your TextEditingController is the key to do that
_searchController.text = data_from_voice;
// or _searchController.text = transcription; Since transcript has some value
});
}
Also, read about TextEditingController Class on what all are the operations you can perform using it. More knowledge to you on this Class will help you in great extent :)
I hope that helps, if not, then please show me where is the function where you are setting the value to transcription. You can assign the value to the same place, like above to _searchController.text and you are good to go. Let me know :)
Related
I am new-ish to flutter and I have come across a problem and I would really appreciate your help.
I have two separate forms on two different screens. Clicking the "Next" button on the first page validates the form and pushes to the second page using Navigator.push(). And all works fine until I come back to the first page using the arrow on the top left corner in the app bar which is automatically created. The data inside the TextFormFields on the first page is still filled out which is good but when I click next (which validates and pushes to the second page using Navigator.push) and go to the second page all the data inside the TextFormFields has disappeared.
My intention is to have the user data entered in the TextFormFields of both forms persistent after Navigating back and forth through different screens.
I have already looked at this stackoverflow page but the solution there did not fix my issue.
I looked into shared_preferences but the people on the Flutter discord suggested not to use it.
Here is the code:
First Page
Second Page
(I used PasteUbuntu for the code as it was a bit too long so I didn't want to copy it in this post)
This is the definition for my formField() function:
class formField extends StatelessWidget {
Function validator;
Function onSaved;
String fieldTitle;
String hintText;
TextEditingController textController;
TextInputType keyboardStyle;
formField(
{this.onSaved,
this.validator,
this.fieldTitle,
this.hintText,
this.textController,
this.keyboardStyle});
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
RichText(
textAlign: TextAlign.left,
text: TextSpan(
text: fieldTitle,
style: GoogleFonts.questrial(
fontSize: 16,
color: Colors.black,
fontWeight: FontWeight.w500,
)),
),
SizedBox(height: 10),
Container(
width: 335,
height: 50,
child: Material(
elevation: 5.0,
borderRadius: BorderRadius.circular(10.0),
child: TextFormField(
validator: validator,
onSaved: onSaved,
textAlignVertical: TextAlignVertical.bottom,
textCapitalization: TextCapitalization.sentences,
keyboardType: keyboardStyle,
controller: textController,
decoration: InputDecoration(
filled: true,
fillColor: Color(0xFFF0F0F0),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Color(0xFFE8E8E8))),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Color(0xFFE8E8E8)),
borderRadius: BorderRadius.circular(8.0),
),
hintText: hintText,
hintStyle:
GoogleFonts.inter(color: Color(0xFFBDBDBD), fontSize: 16),
),
style: GoogleFonts.inter(color: Colors.black, fontSize: 16),
),
),
),
],
);
}
}
I've already read this. how to make clear button appears when text is enter in TextFormField in flutter
but It doesn't work, and also I found that the textfield doesn't recognize the change when text is typed. If you know the solution, I really appreciate it if you let me know.
Here's my code below :
TextField(
controller: _controller,
onChanged: (String word) {
this.word = word;
_controller.text = word;
},
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.w800,
color: Colors.black),
decoration: InputDecoration(
isDense: true,
suffix: _controller.text.length > 0
? Padding(
padding: const EdgeInsetsDirectional.only(
bottom: 2),
child: IconButton(
onPressed: () => _controller.clear(),
icon: Icon(Icons.clear),
iconSize: 25,
color: Colors.black.withOpacity(0.5),
))
: null,
contentPadding:
EdgeInsets.only(left: 8.5, bottom: 3),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.black)),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.black),
),
hintText: "Add text",
hintStyle: TextStyle(
fontSize: 29.0,
color: Colors.black.withOpacity(0.5)),
)),
What I want to make :
First of all, in the onChanged(), you're just assigning the value to controller.text without telling the widget to rebuild according to the changes. Therefore, you must have a setState() inside onChanged().
Second, don't reassign controller.text, since that will cause the error of the cursor always jump to the start (don't ask me why, I just know the error is there). So instead, make a new variable type String and assign value to it in onChanged(). Then when checking the condition to show or hide the suffix icon, check the condition with that new String, not with controller.text.
Try using.
suffix = _controller.text !=null?Padding(
padding: const EdgeInsetsDirectional.only(
bottom: 2),
child: IconButton(
onPressed: () => _controller.clear(),
icon: Icon(Icons.clear),
iconSize: 25,
color: Colors.black.withOpacity(0.5),
))
: null,
I have form field :
This form field will collect all the data from my client.
Each of these field is specific and I want push the entry of each of these field into a ListView.builder according to the name of the field.
For example the field " Alias" has to be push into the listview.builder that you can see above, and the others fields has to be push to another listview.builder in order to build an address book.
this is my code for listview.builder.
Please I accept suggestion how to to that thanks:
Container(
height: 1000,
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (ctx, int) {
return Card(
color: Color(0xFF1f2032),
elevation: 15,
child: Container(
width: 60,
height: 60,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Card(
color: Color(0xfffeaf0d),
child: Container(
height: 40,
width: 40,
child: Icon(Icons.location_on,color: Colors.white,size: 25,)),
),
Text('User id № $int',style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold),),
Text(userDestinationFullName,style: TextStyle(fontWeight: FontWeight.bold,color: Color(0xfffeaf0d),),),
Text(aliasName,style: TextStyle(color: Colors.lightGreenAccent),),
Icon(Icons.cancel,color: Colors.white,)
],
),
));
},
),
),
Ok
the list view is the code I posted above
in such listview I need to have the data that I retrieve from the formfield which the customer will fill up.
For example:
In the field "Alias" into the form customer will write " Home "
this "Home" has to be shown into the listview
Customer will also write as "Nome e Cognome" the full name of the for example "Mario Rossi", then Mario Rossi has to appear into the list view in a single row.
this is the screenshot of the list view.
https://ibb.co/LN2nVtk
as you can see the horizontal list where is + alias, Alias... has to be substitute with the written field that customer fill in the form
vertical ListView has rows with several text, each of these text is a field into the form, so each of these field has to be substitute with the written filled into the form
This is just a field to a form
for example Full name field once filled the content has to be push into the listview as shipmentFullName
Widget FullName() {
return TextFormField(
validator: (value) {
if (value.isEmpty) {
return 'Nome e Cognome obbligatorio';
}
return null;
},
keyboardType: TextInputType.text,
style: TextStyle(color: Color(0xFF1f2032), fontSize: 14),
decoration: InputDecoration(
fillColor: Color(0xfffeaf0d),
filled: true,
labelText: 'Nome e Cognome',
labelStyle: TextStyle(color: Color(0xFF1f2032)),
prefixIcon: Icon(
Icons.person_add,
color: Color(0xFF1f2032),
size: 17,
),
hintStyle: TextStyle(
color: Color(0xFF1f2032),
),
hintText: 'Nome e Cognome del Destinatario',
contentPadding: EdgeInsets.symmetric(vertical: 5, horizontal: 35.0),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Color(0xFF1f2032), width: 1.5),
borderRadius: BorderRadius.circular(5),
),
),
);
}
I am setting a text field which will expands when Enter is pressed in the keyboard
when i tried to set null in max lines it does not show the text inside text field
i even set that expands = true
i used media query size in somewhere which is size.height in the code
i wrapped the text field within the Flexible widget
and add some padding then the total flexible widget is wrapped within a Row
and finally the row is wrapped within a Container
so this code is not working help me to fix this
Container(
height: size.height * .059,
width: double.infinity,
child: new Row(
children: <Widget>[
new Flexible(
child: Padding(
padding: EdgeInsets.only(right: size.width * 0.007),
child: new TextField(
controller: _textFieldController,
textInputAction: TextInputAction.newline,
keyboardType: TextInputType.multiline,
maxLines: null,
expands: true,
style: TextStyle(color: Colors.black),
cursorColor: Colors.blue,
decoration: InputDecoration(
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
borderSide: BorderSide(color: Color(0xff8e9291))),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
borderSide: BorderSide(color: Color(0xff8e9291))),
prefixIcon: Icon(
Icons.message,
color: Color(0xff8e9291),
),
hintText: "Type a message",
hintStyle: TextStyle(
color: Color(0xff8e9291),
),
),
),
),
),
FloatingActionButton(
backgroundColor: Colors.blue[400],
onPressed: () {
},
tooltip: 'Send',
child: RotationTransition(
turns: AlwaysStoppedAnimation(-35 / 360),
child: Icon(
Icons.send,
size: 20,
)),
),
],
),
),
this is the Text field i'm using..
You could remove the height of the Container since that will make a fixed height, and remove the expands of the TextField since that is to make it to fill its parent height.
You could set MaxLine property to null 'maxLines: null`
this will enable textField to Expand Vertical
I tried creating an email textfield with validator using TextFormField. Since the textfield height is too much for my liking, I wrap the TextFormField with Container and set the height to 50. Now the problem is whenever I submitted intended wrong value, the validator will popped out and pushed the textfield, leaving the height much smaller than what I set in Container.
Before submitting:
After submitting:
Here is my codes:
Widget _emailForm() {
return Form(
key: _emailFormKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text("Enter Your Email", style: TextStyle(fontSize: 13.0, fontWeight: FontWeight.bold),),
Padding(padding: EdgeInsets.symmetric(vertical: 4.0),),
Container(
height: 50,
child: TextFormField(
focusNode: _emailFocusNode,
style: TextStyle(fontSize: 11.0, fontWeight: FontWeight.w600),
keyboardType: TextInputType.emailAddress,
controller: _emailTextController,
decoration: InputDecoration(
isDense: true,
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(0.0),),
),
suffixIcon: IconButton(
alignment: Alignment.centerRight,
iconSize: 16.0,
icon: Icon(Icons.clear),
onPressed: () {
if(_emailTextController != null) {
_emailTextController.clear();
FocusScope.of(context).requestFocus(_emailFocusNode);
}
},
),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(0.0),
),
borderSide: BorderSide(
color: Colors.black,
width: 1.0
)
),
errorStyle: _errorTextStyle,
),
validator: (val) {
Pattern pattern = r'#';
RegExp regex = RegExp(pattern);
if(val.isEmpty) return "* Email address can't be empty";
else if(!regex.hasMatch(val)) return "* Invalid email address";
else {
return null;
}
},
),
),
Padding(padding: EdgeInsets.symmetric(vertical: 6.0),),
FlatButton(
child: Text("Join".toUpperCase(), style: TextStyle(color: Colors.white, fontSize: 11),),
onPressed: (){
if(_emailFormKey.currentState.validate()) {
_joinWaitingList();
}
},
color: _themeColor,
),
],
),
);
}
This widget is part of ListView in my build method if that information is helping. Is there any way to solve this problem? Thanks!
The problem is that TextField and TextFormField size themselves to include all of their content and decoration. If you add some error text onto the bottom of the TextFormField, then it will include that in its height. When it tries to size itself to fit into your Container, it doesn't have as much space for the input.
You could work around this by specifying the height of your Container in both the valid and invalid states. You'll have to fiddle with the exact invalid height, but it might look something like this:
Container(
height: _isInvalid ? 100 : 50,
TextFormField(),
),
Another option is to add counterText: ' ' to your InputDecoration and then size the Container to the size that you want. This will give you extra space to fit the error text without needing to change the height of the TextFormField.
Container(
height: 100,
TextFormField(
decoration: InputDecoration(
counterText: ' ',
),
),
),
The cleanest solution, if it's possible for you, may be to not use a Container at all. If you can create the input you want just by using InputDecoration and things like contentPadding etc., it will likely make this a lot cleaner.
hey i think that its works if u use onchanged instead of validator :
onChanged: (val) {
Pattern pattern = r'#';
RegExp regex = RegExp(pattern);
if(val.isEmpty) return "* Email address can't be empty";
else if(!regex.hasMatch(val)) return "* Invalid email address";
else {
return null;
}
},