There's a button on my home page which when clicked should redirect me to another page and click on textformfield on that page,I dont know how to do that
just use autofocus: true on another page
class Home extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: TextButton(
onPressed: () {
Navigator.push(context, MaterialPageRoute(
builder: (context) {
return NextPage();
},
));
},
child: Text("Click")),
),
);
}
}
class NextPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: TextField(
autofocus: true,
),
);
}
}
There is multiple ways to do this depending on your use case
1- if you want to focus on the text form field every time you enter the page you change autofocus property in the textField to true,
TextField(
autofocus:true,
)
2- if you want to trigger focus on a textfield by manually you can use FocusNode object, this focus node will be attached to your text field.
First you need to initialize the object.
FocusNode myFocusNode;
#override
void initState() {
super.initState();
myFocusNode = FocusNode();
}
#override
void dispose() {
// Clean up the focus node when the Form is disposed.
myFocusNode.dispose();
super.dispose();
}
then Attach the focus node object to your text field
TextField(
focusNode: myFocusNode,
);
Now you can use this focus node in a function to focus on this text
// focus on textfield (same as text field pressed)
myFocusNode.requestFocus()
// unfocus on textfield (same as pressing done on textfield or pressing the back button)
myFocusNode.unfocus()
you can pass a flag to the new page you are going to, which will trigger the focus function
Related
I have a form page and there are several TextFields and I want to call a function after clicking outside of one specific textfield. Is there any parameter of TextField that can serve my purpose or any way to do that?
TextFormField have focusNode property, focusNode have addListener callback. which get called when TextFormField having focus and when textformfield losing its focus, with the help of focusnode we can call method when clicking outside specific textfield.
class _MyWidgetState extends State<MyWidget> {
FocusNode firstFocusNode = FocusNode();
FocusNode secondFocusNode = FocusNode();
#override
void initState() {
super.initState();
firstFocusNode.addListener(() {
if (!firstFocusNode.hasFocus) {
method();
}
});
}
void method() {
print("User clicked outside the Text Form Field");
}
#override
void dispose()
{
firstFocusNode.removeListener((){});
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(children: [
TextFormField(focusNode: firstFocusNode),
TextFormField(
focusNode: secondFocusNode,
)
]));
}
}
the solution you are looking for is gestureDetector, but it depends where you want to call the function if you want to call the function only when tapped inside the form area but outside the textfield then wrap the form with gesture detector and use onTap: (){}, or if you want to call the same on whole screen tapped but outside the textfield wrap it around the whole scaffold.
new Scaffold(
body: new GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
//this function will remove the keyboard.
},
I am very new to Flutter and Dart so I am trying to build a simple search app with queries based on a word typed in Flutters showSearch search bar. I understand the listtile that is built to show suggestions to the user, and tapping that suggestion will activate the buildresults widget. However, I want to enable the search button on the keyboard to simply search the inputted word, rather than tapping on the limited suggestion list.
Simple android keyboard
When the button is clicked normally, the keyboard is closed the buildresults is not activated. So far you have to actually click a suggested listtile option. Is there a way to enable the keyboard's search button to search the inputted text? or Is the user limited to the suggested listtile options? I will list my showSearch delegate below:
class StockDelegate extends SearchDelegate<String> {
final stocks = [
"IBM",
"NKLAW",
"DKNGZ",
"DRD",
"PRTS",
"TSLA",
"KIRK",
"VBIV"
];
final suggested = ["IBM", "TSLA", "BNTX"];
#override
// TODO: implement textInputAction
// TODO: implement textInputAction
TextInputAction get textInputAction => super.textInputAction;
#override
List<Widget> buildActions(BuildContext context) {
//actions for app bar
StockProvider _stockProvider =
Provider.of<StockProvider>(context, listen: true);
return [
IconButton(
icon: Icon(Icons.clear),
onPressed: () {
query = '';
}),
];
}
#override
Widget buildLeading(BuildContext context) {
//Leading icon on the left of the app bar
return IconButton(
icon: AnimatedIcon(
icon: AnimatedIcons.menu_arrow,
progress: transitionAnimation,
),
onPressed: () {
close(context, null);
});
}
#override
Widget buildResults(BuildContext context) {
//build results code
}
#override
Widget buildSuggestions(BuildContext context) {
// show when someone search for something
stocks.insert(0, query.toString());
final suggestionList = query.isEmpty
? suggested
: stocks.where((p) => p.startsWith(query)).toList();
return ListView.builder(
itemCount: suggestionList.length,
itemBuilder: (context, index) => ListTile(
onTap: () async {
Provider.of<StockProvider>(context, listen: false)
.searchBySymbol(suggestionList[index]);
if (!stocks.contains(suggestionList[index]))
suggestionList.add(suggestionList[index]);
showResults(context);
},
leading: Icon(Icons.attach_money),
title: Text(suggestionList[index]),
),
);
}
I don't know whether you know about onSubmitted property or not, which is used in the TextField/Text/TextFormField. Since, I cannot see your TexFormField/Text/TextField anywhere, but I think you must be using it somewhere.
So, this is how onFieldSubmitted used, which does the job which you want, that is, when the user hit on the magnifying lens on the keypad, it runs your function
TextFormField(
controller: _yourTextEditingController,
textInputAction: TextInputAction.search,
onFieldSubmitted: (){
// here you do your operation when you hit the
// keypad magnifying lens
// check with print()
print('Pressed via keypad');
}
)
Don't get confused with onSubmitted name, onFieldSubmitted is used in TextFormField/Text/TextField, which uses onSubmitted property. I hope that answers your question :) Let me know, is that was the thing you were looking for.
Override showResults() method similar to buildSuggestions().
override showResults method as follow:
#override
void showResults(BuildContext context) {
super.showResults(context);
showSuggestions(context);
FocusScope.of(context).unfocus();
}
Pretty much what I describe in the title. I have a pile of TextFormFields populated from Firebase when the app launches.
The user should be able to update these, and when they are done, click a submit button to update the database. The database code all works, however there is some bug which works as follows:
TextFormField1: "New Text Entered"
TextFormField2: "Some more text"
TextFormField3: "Another update here"
Now we get to a point where we need to dismiss the keyboard, so that we can see the submit button underneath. As soon as you click the little down arrow to dismiss the keyboard, all the changes above revert back to their original state.
Anyone seen this?
I am prepopulating the data in these fields at runtime, and you can edit and update the text, and it all works fine... except if you minimise the keyboard.
Please tell me that Flutter isn't doing something fundamentally stupid like reloading the widget underneath from scratch every time you ask the keyboard to go away...... It sort of feels like it is.
Yes. It happens to me all the time. It is because the screen rebuilds when the bottom insets (due to keyboard) changes.
Enclose the TextFormField(s) inside a Form and give it a global key.
Use a local variable to store the value of the TextFormField. Update it in onChanged method.
All done!
I shall attach a code for easiness.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: LoginScreen(),
);
}
}
// Login Screen
class LoginScreen extends StatefulWidget {
#override
_LoginScreenState createState() => _LoginScreenState();
static GlobalKey<FormState> _loginScreenFormKey = GlobalKey<FormState>();
}
class _LoginScreenState extends State<LoginScreen> {
String username;
String password;
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Form(
key: LoginScreen._loginScreenFormKey,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(
hintText: 'Enter username',
),
onChanged: (value) {
setState(() {
username = value;
});
},
),
TextFormField(
decoration: InputDecoration(
hintText: 'Enter username',
),
onChanged: (value) {
setState(() {
password = value;
});
},
obscureText: true,
),
RaisedButton(
onPressed: () {
LoginScreen._loginScreenFormKey.currentState.save();
},
child: Text('submit'),
),
],
),
),
),
);
}
}
This is my solution: move the TextEditingController variable from the inside of the "build" method to the outside of the "build" method. Ref in pic The solution
The class that includes those TextFormFields should extends State of StatefulWidget, the local state will be cleared if the dismiss of keyboard causes those fields re-render, hence you need StatefulWidget to save the local state so that it won't be re-rendered
Convert you StatelessWidget to StatefulWidget.
If I have this:
class SomethingState extends State<Something> {
String name;
#override
Widget build(BuildContext context) {
return TextField(
onChange: (text) {
name = text
}
)
}
}
Do I have to wrap name = text in setState to trigger the build method or no because when the user types something in the TextField it already does that?
This is how I have it now and it works, but I want to make sure I understand this correctly.
The value will change without setState but will not change on the UI. To update the UI you must use setState and rebuild the widgets.
This code for the question in the comments
class Homepage extends StatelessWidget {
final controller = TextEditingController();
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Center(child: TextField(controller: controller,),),
FlatButton(child: Text("change"),onPressed: (){
controller.text = 'new text';
},)
],
);
}
}
Is there a way in Flutter to force that the keyboard which opens once I click the TextForm is in English?
I want a TextField to contain only English characters. Is there a way?
Use the following to open default keyboard app with predefined language.
FocusScope.of(context).requestFocus(FocusNode());
There is no way to launch the keyboard in particular language. Users have to do that from their end in keyboard settings. However you may use the RegExp to check if all the characters are in English.
May be this helps!
SystemChannels.textInput.invokeMethod('TextInput.show');
whenever requestFocus is invoked to prevent this situation:
As far as I know, there isn't a way to launch the keyboard in a language.
To open keyboard with the predefined language you need to enable autoFocus in the TextField widget like this:
TextField(
autofocus: true,
)
class _MyHomePageState extends State<MyHomePage> {
final _focusNode = FocusNode();
#override
void initState() {
super.initState();
}
#override
void dispose() {
_focusNode.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
RaisedButton(
child: Text('PROVIDE FOCUS'),
onPressed: () {
FocusScope.of(context).requestFocus(_focusNode);
SystemChannels.textInput.invokeMethod('TextInput.show');
},
),
IgnorePointer(
child: TextField(
focusNode: _focusNode,
),
)
],
),
);
}
}