Related
I have created a contact form with a few textformfields. When I'm using the keyboard I want to also use the the arrows at the top of the keyboard to move to next textformfield. I have already implemented TextInputAction.next so that when clicking on "return" you go to next textformfield, but I also want to include the arrows to do the same to go up/down.
The image below shows the arrows I want to include action on.
This is my current textformfield code:
Widget _createTextField(controller, keyboardType, int maxLength, int maxLines, String hintText, double screenWidth) {
return Expanded(
child: TextFormField(
scrollPadding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
textCapitalization: TextCapitalization.sentences,
textInputAction: TextInputAction.next,
style: TextStyle(fontSize: (screenWidth > maxMobileScreenWidth) ? 16 : 12),
controller: controller,
keyboardType: keyboardType,
maxLength: maxLength,
maxLines: maxLines,
validator: (value) {
if (value!.isEmpty) {
return '* Required field';
}
return null;
},
decoration: InputDecoration(
counterText: "",
filled: true,
hintText: hintText,
hintStyle: const TextStyle(color: Colors.black45),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(10.0)),
fillColor: const Color(0xff9ccb40),
),
),
);
}
You must use the Form() widget, on top of all your TextFromField.
you can use Form(child:Column(children:[])
suggest you to read this article
I am trying to add done button in number type input for a TextFormField in flutter but I could not able to do that.
TextFormField(
key: Key(keyValue),
initialValue: valueBuilder,
onSaved: (text) {
fieldsController.text = text.trim();
},
inputFormatters: [inputFormatters],
keyboardType: TextInputType.phoneNumber,)
I want create a keyboard like the below. For the input text form field.
Change
keyboardType: TextInputType.number
to
keyboardType: TextInputType.numberWithOptions(signed: true, decimal: true)
You don't need a done button just wrap MaterialApp with a GestureDetector
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus &&
currentFocus.focusedChild != null) {
FocusManager.instance.primaryFocus.unfocus();
}
},
child: MaterialApp(
title: "My title",
home:MyHomeScreen(),
),
);
I've just created a package for add basic actions to the current keyboards .
You can take a look here :
https://pub.dartlang.org/packages/keyboard_actions
Usage :
import 'package:flutter/material.dart';
import 'package:keyboard_actions/keyboard_actions.dart';
//...
FocusNode _nodeText1 = FocusNode();
FocusNode _nodeText2 = FocusNode();
FocusNode _nodeText3 = FocusNode();
FocusNode _nodeText4 = FocusNode();
FocusNode _nodeText5 = FocusNode();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Keyboard Actions Sample"),
),
body: FormKeyboardActions(
keyboardActionsPlatform: KeyboardActionsPlatform.ALL, //optional
keyboardBarColor: Colors.grey[200], //optional
nextFocus: true, //optional
actions: [
KeyboardAction(
focusNode: _nodeText1,
),
KeyboardAction(
focusNode: _nodeText2,
closeWidget: IconButton(
icon: Icon(Icons.close),
onPressed: () {},
),
),
KeyboardAction(
focusNode: _nodeText3,
onTapAction: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Text("Custom Action"),
actions: <Widget>[
FlatButton(
child: Text("OK"),
onPressed: () => Navigator.of(context).pop(),
)
],
);
});
},
),
KeyboardAction(
focusNode: _nodeText4,
displayCloseWidget: false,
),
KeyboardAction(
focusNode: _nodeText5,
closeWidget: Padding(
padding: EdgeInsets.all(5.0),
child: Text("CLOSE"),
),
),
],
child: Padding(
padding: const EdgeInsets.all(15.0),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
TextField(
keyboardType: TextInputType.number,
focusNode: _nodeText1,
decoration: InputDecoration(
hintText: "Input Number",
),
),
TextField(
keyboardType: TextInputType.text,
focusNode: _nodeText2,
decoration: InputDecoration(
hintText: "Input Text with Custom Close Widget",
),
),
TextField(
keyboardType: TextInputType.number,
focusNode: _nodeText3,
decoration: InputDecoration(
hintText: "Input Number with Custom Action",
),
),
TextField(
keyboardType: TextInputType.text,
focusNode: _nodeText4,
decoration: InputDecoration(
hintText: "Input Text without Close Widget",
),
),
TextField(
keyboardType: TextInputType.number,
focusNode: _nodeText5,
decoration: InputDecoration(
hintText: "Input Number with Custom Close Widget",
),
),
],
),
),
),
),
);
}
add this to your TextField
TextField(
...
keyboardType: TextInputType.numberWithOptions(signed: true),
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
...
),
This is how to add Done button to your TextFormField when keyboard is opened:
textInputAction: TextInputAction.done,
Please keep in mind that iOS doesn’t support Done on NUMERIC keyboards.
I used this way to handle done button in IOS
keyboardType: Platform.isIOS?
TextInputType.numberWithOptions(signed: true, decimal: true)
: TextInputType.number,
// This regex for only amount (price). you can create your own regex based on your requirement
inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d{0,4}'))],
There is no done button in ios keyboard. Solution is that use "keyboard_actions" plugin otherwise add layout top of keyboard check this
https://blog.usejournal.com/keyboard-done-button-ux-in-flutter-ios-app-3b29ad46bacc
I used the signed option to display the done button. Then I used a TextInputFormatter with a RegEx to limit what the user can input.
new TextFormField(
controller: myController,
keyboardType: TextInputType.numberWithOptions(signed:true, decimal: true),
textInputAction: TextInputAction.done,
onFieldSubmitted: (term) {
_showSnackBar(context, double.parse(myController.text));
},
onEditingComplete: () {
_showSnackBar(context, double.parse(myController.text));
},
decoration: const InputDecoration(
helperText: "Actual",
hintText: "Units used",
border: UnderlineInputBorder(),
icon: Icon(Icons.keyboard),
),
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(RegExp(r'^\d*\.?\d*$')),
],
),
There is no done button in iOS but we can check the length of the input and clear focus to hide the numberpad keyboard.
Implement like below,(it'll work with fix length of number value)
onChanged: (val) {
if (val.length == 10) { //10 is the length of the phone number you're allowing
FocusScope.of(context).requestFocus(FocusNode());
}
}
I'm trying to build a simple login screen here using basic Textfields, but I can't get a keyboard to appear in the Simulator.
Input via the physical keyboard works just fine, but in the iOS Simulator there is no keyboard visible. Do I have to explicitly open it or something?
Feels like I'm missing something really basic here.
buildLoginScreen() {
return new Container(
padding: EdgeInsets.only(left: 50.0, right: 50.0),
child: new Column(
children: <Widget>[
new TextField(
style: new TextStyle(color: Colors.white),
autofocus: true,
autocorrect: false,
decoration: new InputDecoration(
labelText: 'Login',
),
onChanged: (text) { _userLoginEmail = text; },
),
new TextField(
autofocus: false,
autocorrect: false,
obscureText: true,
decoration: new InputDecoration(
labelText: 'Password'
),
onChanged: (text) { _userLoginPassword = text; },
)
],
),
);
}
Solution
Turns out if the hardware keyboard is connected, it will suppress the software keyboard. cmd + shift + k disconnects the hardware keyboard or cmd + k toggles the software keyboard.
CMD +
Shift + K toggles connectivity of the hardware keyboard, which will open the software keyboard by default if the other one is disconnected.
CMD + K toggles the visibility of the software keybaord.
In Android and iOS it is possible to change the enter/return key of the keyboard to e.g. a "Go" button (and other options).
On top, we can see the regular "Return" button on both systems, which is the one you get by default with no modifications in both Android & iOS native and Flutter.
Below that, there is another setting, again on both systems, which you can simply adjust in your native application. It is the "Go" button in this case.
The input action for a TextField (or TextFormField) can be specified like this (here, the Go button):
TextField(
textInputAction: TextInputAction.go
...
)
List of all available input actions.
This is how you can use textInputAction:
TextField(
textInputAction: TextInputAction.search,
onSubmitted: (value) {
print("search");
},
decoration: InputDecoration(
border: InputBorder.none,
prefixIcon: Icon(Icons.search),
hintText: 'Search ',
contentPadding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
),
);
This is currently not possible.
Although you can edit flutter sources to make it possible quite easily.
The following edits are :
flutter/lib/src/widgets/editable_text.dart
Change _openInputConnection line ~430 to
void _openInputConnection() {
if (!_hasInputConnection) {
final TextEditingValue localValue = _value;
_lastKnownRemoteTextEditingValue = localValue;
_textInputConnection = TextInput.attach(this,
new TextInputConfiguration(
inputType: widget.keyboardType,
obscureText: widget.obscureText,
autocorrect: widget.autocorrect,
inputAction: widget.keyboardType == TextInputType.multiline
? TextInputAction.newline
: TextInputAction.done
)
)..setEditingState(localValue);
}
_textInputConnection.show();
}
In the same file, also declare a new field on EditableText class (not the state one) ~line 280
final TextInputAction textInputAction;
And assign it in EditableText constructor above line 164
this.textInputAction,
flutter/lib/src/material/text_field.dart
Same story. Add a new field, but to TextField instead :
final TextInputAction textInputAction;
and add the following to it's constructor :
this.textInputAction,
Finally, pass that new field as parameter to EditableText line 479 :
textInputAction: widget.textInputAction,
Done.
You can now inside your app specify a custom TextInputAction. This won't break existing TextField. It just adds the ability to override the default behavior.
new TextField(
keyboardType: TextInputType.text,
textInputAction: TextInputAction.newline,
),
basically we are use two types of text input fields,
TextField and TextFormField,
so,
for TextField,
TextField(
textInputAction: TextInputAction.go
.......
)
for TextFormField,
TextFormField(
textInputAction: TextInputAction.go,
........
)
both have textInputAction property, we can use this
Here is how to add the action button and also listen to onTap
For TextField
TextField(
textInputAction: TextInputAction.go,
onSubmitted: (value) {
print("Go button is clicked");
},
decoration: InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
),
);
For TextFormField
TextFormField(
textInputAction: TextInputAction.go,
onFieldSubmitted: (value) {
print("Go button is clicked");
},
decoration: const InputDecoration(
hintText: "Type your search here",
hintStyle: TextStyle(color: Colors.black26),
filled: true,
fillColor: Colors.white,
border: OutlineInputBorder(
borderSide: BorderSide.none,
borderRadius: BorderRadius.all(Radius.circular(40.0)),
),
contentPadding:
EdgeInsets.symmetric(horizontal: 20.0, vertical: 16.0)),
)
One angle ... I have not explored all the "keyboardType" options within the TextField (optional parameter of TextInputType).
But there are some obvious different keyboards for 'emailAddress' and 'datetime' and 'phone' - one of those options may emit the keyboard that you are looking for ...
Anyone looking for UIReturnKeyDone is like this:
TextField(
textInputAction: TextInputAction.done
...
)
It may sound easy but How can we do a multi-line editable textfield in flutter? TextField works only with a single line.
Edit: some precisions because seems like it's not clear.
While you can set multiline to virtually wrap the text content, it's still not multiline. It's a single line displayed into multiple lines.
If you want to do something like this then you can't. Because you don't have access to ENTER button. And no enter button means no multiline.
To use auto wrap, just set maxLines as null:
TextField(
keyboardType: TextInputType.multiline,
maxLines: null,
)
If the maxLines property is null, there is no limit to the number of lines, and the wrap is enabled.
If you want your TextField be adapted to the user input then do this:
TextField(
keyboardType: TextInputType.multiline,
minLines: 1,//Normal textInputField will be displayed
maxLines: 5,// when user presses enter it will adapt to it
);
here you can set the max lines to whatever you want and you are good to go.
In my opinion setting the maxlines to null is not a good choice that's why we should set it to some value.
Although other people already mentioned that the keyboard type "TextInputType.multiline" can be used, I wanted to add my implementation of a TextField that automatically adapts its height when a new line is entered, as it is often desired to immitate the input behaviour of WhatsApp and similar apps.
I'm analyzing the number of '\n' chatacters in the input for this purpose each time the text is changed. This seems to be an overkill, but unfortunately I didn't find a better possibility to achieve this beahivour in Flutter so far and I didn't notice any performance problems even on older smartphones.
class _MyScreenState extends State<MyScreen> {
double _inputHeight = 50;
final TextEditingController _textEditingController = TextEditingController();
#override
void initState() {
super.initState();
_textEditingController.addListener(_checkInputHeight);
}
#override
void dispose() {
_textEditingController.dispose();
super.dispose();
}
void _checkInputHeight() async {
int count = _textEditingController.text.split('\n').length;
if (count == 0 && _inputHeight == 50.0) {
return;
}
if (count <= 5) { // use a maximum height of 6 rows
// height values can be adapted based on the font size
var newHeight = count == 0 ? 50.0 : 28.0 + (count * 18.0);
setState(() {
_inputHeight = newHeight;
});
}
}
// ... build method here
TextField(
controller: _textEditingController,
textInputAction: TextInputAction.newline,
keyboardType: TextInputType.multiline,
maxLines: null,
)
TextFormField(
minLines: 2,
maxLines: 5,
keyboardType: TextInputType.multiline,
decoration: InputDecoration(
hintText: 'description',
hintStyle: TextStyle(
color: Colors.grey
),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0)),
),
),
),
While this question is rather old, there is no extensive answer that explains how to dynamically resize the TextField with little developer effort. This is especially of major importance when the TextField is either placed in a flexbox such as ListView, SingleChildScrollView, etc. (the flexbox will not be able to determine the intrinsic size of an expandable TextField).
As suggested by many other users, build your TextField like so:
TextField(
textInputAction: TextInputAction.newline,
keyboardType: TextInputType.multiline,
minLines: null,
maxLines: null, // If this is null, there is no limit to the number of lines, and the text container will start with enough vertical space for one line and automatically grow to accommodate additional lines as they are entered.
expands: true, // If set to true and wrapped in a parent widget like [Expanded] or [SizedBox], the input will expand to fill the parent.
)
How to cope with the missing intrinsic height of the TextField?
Wrap the TextField in a IntrinsicHeight class to provide the dynamically computed intrinsic height of the expandable TextField to its parent (when requested via e.g. flexbox).
1. Fixed height:
(A) Based on lines:
TextField(
minLines: 3, // Set this
maxLines: 6, // and this
keyboardType: TextInputType.multiline,
)
(B) Based on height:
SizedBox(
height: 200, // <-- TextField expands to this height.
child: TextField(
maxLines: null, // Set this
expands: true, // and this
keyboardType: TextInputType.multiline,
),
)
2. Flexible height:
Use a Column and wrap the TextField in Expanded:
Column(
children: [
Expanded(
child: TextField(
maxLines: null, // Set this
expands: true, // and this
keyboardType: TextInputType.multiline,
),
),
],
)
(Optional) Set decoration:
You can se this decoration to any of the above TextField:
decoration: InputDecoration(
hintText: 'Write a message',
filled: true,
)
You have to use this line in the TextField widget :
maxLines: null,
if didn't work , just note that you have to delete this :
textInputAction: TextInputAction.next
it's disable multi line property action in the keyboard ..
use this
TextFormField(
keyboardType: TextInputType.multiline,
maxLines: //Number_of_lines(int),)
This Code Worked for me, Also I'm able to use ENTER for web & mobile.
#override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
child: ConstrainedBox(
// fit: FlexFit.loose,
constraints: BoxConstraints(
maxHeight: height,//when it reach the max it will use scroll
maxWidth: width,
),
child: const TextField(
keyboardType: TextInputType.multiline,
maxLines: null,
minLines: 1,
decoration: InputDecoration(
fillColor: Colors.blueAccent,
filled: true,
hintText: "Type ",
border: InputBorder.none,
),
),
),
)
]);
}
TextField has maxLines property.
Use Expanded widget for dynamic feels
Expanded(
child: TextField(
keyboardType: TextInputType.multiline,
minLines: 1,
maxLines: 3,
),
)
if above once not worked for you then try add minLines also
TextField(
keyboardType: TextInputType.multiline,
minLines: 3,
maxLines: null);
For autowrap just use null for maxLines
TextFormField(
keyboardType: TextInputType.multiline,
maxLines: null,
)
or
TextField(
keyboardType: TextInputType.multiline,
maxLines: null,
)
Official doc states:
The maxLines property can be set to null to remove the restriction on the number of lines. By default, it is one, meaning this is a single-line text field.
NOTE: maxLines must not be zero.
Specify TextInputAction.newline to make a TextField respond to the enter key and accept multi-line input:
textInputAction: TextInputAction.newline,
use this
Expanded(
child: TextField(
controller: textMessageController,
keyboardType: TextInputType.multiline,
textCapitalization: TextCapitalization.sentences,
minLines: 1,
maxLines: 3,
onChanged: ((value) {
setState(() {
_messageEntrer = value;
});
}),
decoration: InputDecoration(
hintText: "Type your message here",
hintMaxLines: 1,
contentPadding:
const EdgeInsets.symmetric(horizontal: 8.0, vertical: 10),
hintStyle: TextStyle(
fontSize: 16,
),
fillColor: Colors.white,
filled: true,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
borderSide: const BorderSide(
color: Colors.white,
width: 0.2,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
borderSide: const BorderSide(
color: Colors.black26,
width: 0.2,
),
),
),
),
),