Reputation: 83
I have a Widget that renders a ListView of TextFormFields to input data. However, I want to change the keyboard type for one of my textfields dynamically. Here is an overview of the Widget:
class CreateTodo extends StatefulWidget {
@override
_CreateTodoState createState() => _CreateTodoState();
}
class _CreateTodoState extends State<CreateTodo> {
final _formKey = GlobalKey<FormState>();
final double formWidth = 175.0;
final Map<String, Icon> itemsMap = {
'Heading': Icon(Icons.title),
'Description': Icon(Icons.edit),
'Date': Icon(Icons.calendar_today)
};
final items = ['Heading', 'Description', 'Date'];
_changeKeyboardType(entry) {
if (entry == "Description") {
return TextInputType.multiline;
}
return TextInputType.text;
}
ListView createListItems() {
return ListView.builder(
padding: EdgeInsets.only(
left: 50.0,
right: 50.0,
top: 20.0
),
scrollDirection: Axis.vertical,
itemCount: 3,
itemBuilder: (context, index) {
var currentHeading = this.items[index];
var currentIcon = this.itemsMap[currentHeading];
return Padding(
padding: EdgeInsets.only(bottom: 50.0),
child: new TextFormField(
validator: (input) {
if (input.isEmpty) {
return 'You must enter a ${currentHeading.toLowerCase()} for your to-do';
}
},
keyboardType: this._changeKeyboardType(currentHeading),
decoration: new InputDecoration(
prefixIcon: currentIcon,
labelText: currentHeading,
border: OutlineInputBorder(),
),
)
);
}
);
}
@override
Widget build(BuildContext context) {
return Form(
autovalidate: true,
child: Expanded(
child: (this.createListItems())
)
);
}
}
The main line that isn't working is: keyboardType: this._changeKeyboardType(currentHeading)
... Am I approaching this problem the wrong way? Any direction will be super helpful. I basically want the textFormFeld for the description being multiline so users can have a better visualization of their description.
Upvotes: 8
Views: 6551
Reputation: 1
My solution, inspired in Can Rau using RadioListTile, when user choose one tile, it changes the input of a search field. first define a variable for the keyboard type :
TextInputType keyboard = TextInputType.text;
in the Onchange off the RadioListTile choose whatever type you need, for example number:
RadioListTile( ...
onChanged: ((value) {keyboard = TextInputType.number;
setState(() {_textformfieldFocus.requestFocus();});
_textformfieldFocus.unfocus();
Future.delayed(const Duration(milliseconds: 10),() {
FocusScope.of(context).requestFocus(_textformfieldFocus);
});}),
And in the TextFormField :
TextFormField( ...
keyboardType : keyboard,
This has no delay and doesn´t shows 2 keyboards
Upvotes: 0
Reputation: 3819
My working solution for now:
// Where entry is an object containing its focusNode and textInputType
entry.focusNode.unfocus();
setState(() {
entry.textInputType = type;
});
// The delay was necessary, otherwise only the 2nd tap would actually change
Future.delayed(const Duration(milliseconds: 1), () {
FocusScope.of(context).requestFocus(entry.focusNode);
});
Only downside I couldn't fix so far is that the keyboard is disappearing before it re-appears with the new TextInputType
.
Google's Spreadsheet app does it instantaneous without the close, would love to know if and how that'll be doable in Flutter.
You'd have to change your logic as my example is asynchronous.
Let me know if that helps or if you need more help.
Or, if you've already figured it out, how you did it
Credits: It's inspired by https://stackoverflow.com/a/58498474/3484824
Upvotes: 7