I made a code that displays a String Array using RadioListTile, but I don't know how to exactly get the user input when he/she selects one option from the list. I'm trying to use controller, but I'm not pretty sure how to use it in this ocation. Any advice? or comments? Here is my code:
///Here is the variable I use to get the user's answer.
TextEditingController userAns = TextEditingController();
///Here I'm using RadioListTile to display all the options and let the user to select one of them.
String selectedOption = '';
List<Widget> checkWhatOptionsDisplay(var question){
///Get question options and check what type of options display.
List<Widget> displayOptions = [];
var options = question.options;
if(options==""){
displayOptions.add(
TextField(
controller: userAns,
keyboardType: TextInputType.text,
decoration: InputDecoration(
hintText: 'Answer Fill in Blank',
labelText: 'Answer Fill in Blank',
),
)
);
}else{
for(String option in options){
displayOptions.add(
RadioListTile(
value: option,
groupValue: selectedOption,
title: Text(option),
onChanged:(currentOption){
setSelectedOption(currentOption);
} ,
selected: selectedOption == option,
)
);
}
}
return displayOptions;
}
setSelectedOption(var option) {
setState(() {
selectedOption = option;
});
}
Related
This is my search code. It works by typing id the codes to display the information.
onSearch(String text) async {
if (text.isNotEmpty) {
List<Item> itemList = [];
for (var item in items) {
if (item.custnum == text.toLowerCase().toUpperCase()) {
itemList.add(item);
}
}
setState(() {
searchitems.clear();
searchitems.addAll(itemList);
print('name : ${searchitems[0].name}');
// if (searchitems.isEmpty) {
// searchitems = [];
// print('searchitems : ${searchitems[0].address!.length}');
// print('searchitems : ${searchitems[0].address!}');
});
} else {
setState(() {
searchCus.clear();
searchitems.clear();
// searchitems.addAll(items);
print('searchitems : $searchitems');
});
}
}
This is my textformfield, it can find and display data. But what I will do is Getting a code from another page It's received and shows the code. But it doesn't show me the information. It has to delete and type at least 1 new password to show the information. Please help me i tried a lot.
TextFormField(
initialValue:
'${searchCus.isEmpty ? "" : searchCus[widget.indexCus].custnum}',
onChanged: onSearch,
decoration: InputDecoration(
labelText: 'custnum',
labelStyle: TextStyle(fontFamily: 'supermarket', fontSize: 14),
isDense: true,
),
),
The reason the initial value not do the search is that you search logic is only works when you type in the textfield, if your initial value come from class constructor you can call onSearch in initState like this:
#override
void initState() {
super.initState();
if(searchCus.isNotEmpty){
onSearch(searchCus[widget.indexCus].custnum);
}
}
I use TextFormField to get stored value from Firestore and display it to user in it's (edit profile) page,with ability to change field value.
My question is:
how can i enable initial value(to get stored value) and controller to pick entered value by the user.
I read the document and i know i can't use both together,but is there an idea to allow textfield to get stored value and edit it in the same time?
TextFormField(
controller: phone_controller,
keyboardType: TextInputType.number,
decoration: InputDecoration(
icon: const Icon(Icons.phone),
hintText: phone,
// labelText: phone,
floatingLabelBehavior: FloatingLabelBehavior.never,
),
validator: (value) {
String pattern = r'(^(?:[+0]9)?[0-9]{10,12}$)';
RegExp regExp = new RegExp(pattern);
if (value.isEmpty || !regExp.hasMatch(value) ) {
return 'Please enter valid phone number like 01001234567';
}
return null;
},
)
In your initState, you can set the initial value of the controller.
#override
void initState() {
super.initState();
phone_controller.text = 'phone_no';
}
phone_controller now has a default value;
GOAL: when editing information it goes to a Form that has an initial value equal to the information at present.
The code below works because it has the property 'initialValue'
TextFormField(
maxLines: 1,
autofocus: true,
initialValue: _currentProditem.producttitle,
style: TextStyle(
color: Colors.black87,
fontWeight: FontWeight.w400,
fontSize: 18.0,
fontFamily:'Cabin',
),
but the code below does not work because the properties 'initialValue' and 'controller' are conflicting. That's why I commented the property 'initialValue' in the code below. But I want to put the initialValue somewhere so I can achieve the above goal.
TextFormField(
controller: _controller,
maxLines: 1,
autofocus: true,
// initialValue: _currentProditem.price,
keyboardType: TextInputType.number,
onChanged: (string) {
string = '${_formatNumber(string.replaceAll(',', ''))}';
_controller.text = string;
Timer(Duration(milliseconds: 1), () {
_controller.selection = TextSelection.fromPosition(TextPosition(offset: string.length));
});
},
so I researched how to put IntialValue and found that you need to add the code below
final _controller = TextEditingController(text: 'some text');
I tried changing the the word 'some text' to '_currentProditem.price' but there was a problem with the word '_currentProditem' it says 'error: Only static members can be accessed in initializers.'
For reference the word '_currentProditem' can be found on the code below
class ItemNotifier with ChangeNotifier {
List<Proditem> _itemList = [];
Proditem _currentProditem;
UnmodifiableListView<Proditem> get itemList => UnmodifiableListView(_itemList);
Proditem get currentProditem => _currentProditem;
set itemList(List<Proditem> itemList) {
_itemList = itemList;
notifyListeners();
}
set currentProditem(Proditem proditem) {
_currentProditem = proditem;
notifyListeners();
}
}
only static fields can be accessed outside any method
so, just initialise the _controller empty
final _controller = TextEditingController();
while building or in initState set the value
_controller.text = currentPrice;
as the controller has a setter named text, its easy to update the value dynamically like when a button is pressed
TextField controlled controller.addListener(() gets called multiple time after pressing the clear button, this will only happen if we are clearing it.
Snippet:
TextEditingController controller = new TextEditingController();
TextField field = new TextField(
controller: controller,
autofocus: true,
);
controller.addListener(() {
print("Pressed cancel button");
});
Video Link
Note: While adding characters in TextField listener method gets called only ones.
I guess that would be a defect on flutter, a possible solution would be to use onChanged()
TextField field = new TextField(
autofocus: true,
onChanged: (String value) {
print("Pressed clear button");
},
);
I have the same problem with Nexus 6p when used with API level 23 and Pixel with API 25.
but this problem did not occurs with Pixel with API28 and it does not occurs with Nexus6P with API26.
exact code from https://flutter.dev/docs/cookbook/forms/text-field-changes was used.
1. We need to create our own .clear() method
void clearField() {
print("c: clearField");
var newValue = textController.value.copyWith(
text: '',
selection: TextSelection.collapsed(offset: 0),
);
textController.value = newValue;
callApi('');
}
// and call it by :
child: TextField(
controller: textController,
autofocus: true,
decoration: InputDecoration(
suffixIcon: IconButton(
icon: Icon(Icons.close),
onPressed: clearField, // call
),
),
),
2. We need to carefully handle changes
void changesOnField() {
print("c: changesOnField");
String text = textController.text;
if (text.isNotEmpty) { // set this
callApi(text);
}
}
Full Code
You may look into this repo and build it locally Github
Result
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.