How AutoFocus Textfield in flutter - flutter

I have a problem while developing my app - how can I auto-focus a textfield after completing input on the previous field, without having to click the textfield?

Use focusNode property and onEditingComplete event. Event trigger after user click on enter on first textfield, after that focusNode request focus for the second TextField.
For example:
FocusNode focusNode = FocusNode();
#override
Widget build(BuildContext context) => Scaffold(
body: Column(
children: <Widget>[
TextField(
autofocus: true,
onEditingComplete: (() => focusNode.requestFocus())
),
TextField(
focusNode: focusNode,
)
]
)
);
More info at: https://flutter.dev/docs/cookbook/forms/focus

TextField(
onEditingComplete: () => FocusScope.of(context).nextFocus(),
),
For the last textfield you would change the 'nextFocus()' to 'unfocus()'

return Focus(
child: TextField(
onChanged: (value) => context.read<SignupBloc>().add(SignupPasswordChanged(value)),
controller: controller,
keyboardType: TextInputType.visiblePassword,
obscureText: true,
key: const Key('signupForm_passwordInput_textField'),
decoration: InputDecoration(
labelText: 'Password *',
errorText: state.password.invalid
? 'Passwords must be at least 10 characters in length\nand a minimum of 1 '
'upper case and 1 lower case letter [A-Za-z]'
: null,
),
),
);

you can also try with
textInputAction: TextInputAction.next
in TextFormField

Related

Flutter,I want my textfield with focus but hiding keyboard?

I need to scan data through a physical device using flutter textfield, but I don't have a solution yet I have gone through many and nothing works for me, please someone helps with this.
TextFormField(
focusNode: loginTextfieldFocus,
style: const TextStyle(fontSize: 15),
controller: loginTextController,
decoration: decoration(context, loginTextController),
onChanged: (val) {
if (val.contains('\n') || val.contains('\r')) {
Log.d("LoginTextfield Entered");
}
},
),
This is not the proper way to do , but somehow i managed to do it.
TextFormField(
autofocus: true,
enabled: isEditable,
showCursor: isEditable,
readOnly: true,
keyboardType: TextInputType.none,
focusNode: textfieldFocus,
controller: textfieldCtr
),
//Called this under widget build
#override
Widget build(BuildContext context) {
SchedulerBinding.instance.addPostFrameCallback((Duration _) {
FocusScope.of(context).requestFocus( textfieldFocus);
});
To receive scan data from device i used RawKeyboardListener. For scanning you can refer it here (flutter Enter event not found on zebra tc77?)
Yes, I have the same issue. I have solve by changing onChanged to validator because onChange is keep reloading your state thatswhy your keyboard is automatically dismiss every time.
validator: (value) {
if (value != null && value.trim().length < 10) {
return 'This field requires a minimum of 10 characters';
}
return null;
},
Try this
Widget build(BuildContext context) {
Future.delayed(const Duration(), () => SystemChannels.textInput.invokeMethod('TextInput.hide'));
return Scaffold(
body: TextField(
autofocus: true,
),
);
}

onEditingComplete is not called after unfocus

I have a TextField like this. The additional code is necessary to show that in different situations, I do various focus manipulation.
final node = FocusScope.of(context);
Function cleanInput = () => {controller.text = controller.text.trim()};
Function onEditingComplete;
Function onSubmitted
TextInputAction textInputAction;
if (!isLast) {
onEditingComplete = () => {
cleanInput(),
node.nextFocus(),
};
onSubmitted = (_) => {cleanInput()};
textInputAction = TextInputAction.next;
} else {
onEditingComplete = () => {
cleanInput(),
};
onSubmitted = (_) => {
cleanInput(),
node.unfocus(),
};
textInputAction = TextInputAction.done;
}
Widget textInput = TextField(
textInputAction: textInputAction,
controller: controller,
onEditingComplete: onEditingComplete,
onSubmitted: onSubmitted,
keyboardType: textInputType,
));
As you can see, I have functions I want to run onEditingComplete. However, this only gets called when I press the Next or Done buttons on my keyboard (or the Enter key in an emulator). If I change focus by tapping on a different field, this function does not get called.
I have tried using a Focus or FocusNode to help with this, but when I do so, the onEditingComplete function itself no longer works.
How can I get the desired effect here while everything plays nicely together?
Focus widget
Wrapping fields in a Focus widget might do the trick.
The Focus widget will capture focus loss events for children. With its onFocusChange argument you can call arbitrary functions.
Meanwhile, the onEditingComplete argument of TextField is unaffected and will still be called on the software keyboard "Next/Done" keypress.
This should handle field focus loss for both "Next/Done" keypress and user tapping on another field.
import 'package:flutter/material.dart';
class TextFieldFocusPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
// ↓ Add this wrapper
Focus(
child: TextField(
autofocus: true,
decoration: InputDecoration(
labelText: 'Name'
),
textInputAction: TextInputAction.next,
// ↓ Handle focus change on Next / Done soft keyboard keys
onEditingComplete: () {
print('Name editing complete');
FocusScope.of(context).nextFocus();
},
),
canRequestFocus: false,
// ↓ Focus widget handler e.g. user taps elsewhere
onFocusChange: (hasFocus) {
hasFocus ? print('Name GAINED focus') : print('Name LOST focus');
},
),
TextField(
decoration: InputDecoration(
labelText: 'Password'
),
),
],
),
),
),
);
}
}
Please add a focus node to your textfield and add a listener to your focus node to trigger when it unfocuses
final node = FocusScope.of(context);
node.addListener(_handleFocusChange);
void _handleFocusChange() {
if (node.hasFocus != _focused) {
setState(() {
_focused = node.hasFocus;
});
}
}
Widget textInput = TextField(
//you missed this line of code
focusNode: node,
textInputAction: textInputAction,
controller: controller,
onEditingComplete: onEditingComplete,
onSubmitted: onSubmitted,
keyboardType: textInputType,
));
And also you can validete automatically by adding autoValidate to your code like below:
Widget textInput = TextField(
//add this line of code to auto validate
autoValidate: true,
textInputAction: textInputAction,
controller: controller,
onEditingComplete: onEditingComplete,
onSubmitted: onSubmitted,
keyboardType: textInputType,
));
FocusNode _node;
bool _focused = false;
#override
void initState() {
super.initState();
_node.addListener(_handleFocusChange);
}
void _handleFocusChange() {
if (_node.hasFocus != _focused) {
setState(() {
_focused = _node.hasFocus;
});
}
}
#override
void dispose() {
_node.removeListener(_handleFocusChange);
_node.dispose();
super.dispose();
}
TextFormField(
focusNode: _node)

Respond to 'done' button in TextFormField

I want to respond to the user pressing the 'done' button on their keyboard when typing in a TextFormField.
Code so far:
TextFormField(
autofocus: true,
textInputAction: TextInputAction.done,
decoration: InputDecoration(
labelText: 'ENTER YOUR TASK'
),
),
use onFieldSubmitted or onEditingComplete property.
onEditingComplete
When a completion action is pressed, such as "done", "go", "send", or "search", the user's content is submitted to the controller and then focus is given up.
When a non-completion action is pressed, such as "next" or "previous", the user's content is submitted to the controller, but focus is not given up because developers may want to immediately move focus to another input widget within onSubmitted.
Example,
TextFormField(
onEditingComplete: (){
//do your stuff
},
)
onFieldSubmitted
onSubmitted is called when the user indicates that they are done editing the text in the field.
Example,
TextFormField(
onFieldSubmitted: (val){
// process
},
)
TextEditingController _textEditingController = new TextEditingController();
TextFormField(
controller: _textEditingController,
autofocus: true,
textInputAction: TextInputAction.done,
onEditingComplete: () {
FocusScope.of(context).requestFocus(new FocusNode());
print(_textEditingController.text);
//TODO your Response code for user
},
decoration: InputDecoration(labelText: 'ENTER YOUR TASK'),
),

How to check whether TextFormField is focused or not

I have a TextFormField with focusNode:
TextFormField(
key: Key('login-username-field-key'),
controller: loginTextController,
textInputAction: TextInputAction.next,
keyboardType: TextInputType.text,
onFieldSubmitted: (term){
_changeFocusField(context, _loginFocus, _passwordFocus);
},
focusNode: _loginFocus,
decoration: InputDecoration(
labelText: AppLocalizations.of(context).loginFieldUsername
),
),
And then:
// Check that text field initially is not focused
final TextFormField textField = tester.widget(find.byKey(Key('login-username-field-key')));
expect(textField.focusNode.hasFocus, isFalse);
But from the docs I saw that TextFormField doesn't have 'focusNode' property (like TextField.focusNode.hasFocus).
So how to check that behavior?
PS I mean we can use FocusNode listeners, but I don't want to do that just for testing purposes. It should be really simply field.focusNode like for TextField.
You should add listener, where you can check state of your textFormField.
The method hasFocus return true or false.
#override
void initState() {
super.initState();
_loginFocus.addListener(_onFocusChange);
}
void _onFocusChange(){
debugPrint("Focus: "+_focus.hasFocus.toString());
}

Changing focus from one text field to the next in Flutter

I have two textFormField widgets. Once the user has completed the first text field I would like to focus on the next textField. Is there a way to do this in Flutter? Currently, the done button just closes the keyboard. I was guessing the focusNode class might be the answer to this but not really sure how that works does anyone have any good examples of focusNode class? Thanks in advance.
Yes, FocusNode and the onFieldSubmitted from a TextFormField are probably the way to go.
FocusScope.of(context).requestFocus(focusNode);
Here is an example that may help:
FocusNode textSecondFocusNode = new FocusNode();
TextFormField textFirst = new TextFormField(
onFieldSubmitted: (String value) {
FocusScope.of(context).requestFocus(textSecondFocusNode);
},
);
TextFormField textSecond = new TextFormField(
focusNode: textSecondFocusNode,
);
// render textFirst and textSecond where you want
You may also want to trigger FocusScope.of() from a button rather than onFieldSubmitted, but hopefully the above example gives you enough context to construct an appropriate solution for your use case.
Screenshot:
No need to use FocusNode
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
TextField(
decoration: InputDecoration(hintText: 'First Name'),
textInputAction: TextInputAction.next,
onEditingComplete: () => FocusScope.of(context).nextFocus(),
),
TextField(
decoration: InputDecoration(hintText: 'Last Name'),
textInputAction: TextInputAction.done,
onSubmitted: (_) => FocusScope.of(context).unfocus(),
),
],
),
);
}
There's a similar method like in Android.
Add
textInputAction
parameter to the TextFormField Widget, then add the property as;
TextInputAction.next
This is how I did it:
var _focusNodes = List.generate(6, (index) => FocusNode()));
And in the TextFormField:
TextFormField(
focusNode: _focusNodes[i],
maxLines: 1,
textInputAction: TextInputAction.next,
onChanged: (text) {
if (i < _controllers.length) {
if (text.isEmpty)
_focusNodes[i - 1].requestFocus();
else
_focusNodes[i + 1].requestFocus();
}
},
),