I have 8 TextFiled and for each I want to prescribe a focus so that the color changes. But I have an error - The getter 'hasFocus' was called on null. How can I fixed that?
class _EditAccountScreenState extends State<EditAccountScreen> {
FocusNode _focusNodeFio;
FocusNode _focusNodeCompany;
...
#override
void initState() {
super.initState();
_focusNodeFio = FocusNode();
_focusNodeCompany = FocusNode();
...
}
#override
void dispose() {
_focusNodeFio.dispose();
_focusNodeCompany.dispose();
...
super.dispose();
}
#override
Widget build(BuildContext context) {
.......
Padding(
child: TextField(
focusNode: _focusNodeFio,
onTap: () {
setState(() {
FocusScope.of(context).requestFocus(_focusNodeFio);
});
},
decoration: InputDecoration(
labelText: 'Contacts',
labelStyle: TextStyle(
color: _focusNodeFio.hasFocus ? Colors.teal[300] : Colors.grey
),
contentPadding:
This is working!
final FocusNode _fNode = FocusNode();
#override
Widget build(BuildContext context) {
return Scaffold(
body: TextField(
focusNode: _fNode,
onTap: () => FocusScope.of(context).requestFocus(_fNode),
decoration: InputDecoration(
labelText: 'Contacts',
labelStyle: TextStyle(color: _fNode.hasFocus ? Colors.teal[300] : Colors.grey),
),
),
);
}
Related
This question already has answers here:
Invalid Constant Value using variable as parameter
(9 answers)
Closed 22 days ago.
I am getting an error in my Flutter app when trying to run it. The error message is "Invalid constant value." and it is pointing to this specific line (line 4 and 45) of code (obscureText).
The error seems to be related to the use of the const keyword in this line. I am trying to create a to hide and show password text, but the const keyword is causing an issue. Can someone please explain what this error means and how I can resolve it in my code?
import 'package:flutter/material.dart';
void main() {
runApp(const RunMyApp());
}
class RunMyApp extends StatefulWidget {
const RunMyApp({super.key});
#override
State<RunMyApp> createState() => _RunMyAppState();
}
class _RunMyAppState extends State<RunMyApp> {
bool passwordVisible = false;
final passwordController = TextEditingController();
bool obscureText = false;
#override
void initState() {
super.initState();
passwordVisible = true;
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(primarySwatch: Colors.green),
home: Scaffold(
appBar: AppBar(
title: const Text('Show or Hide Password in TextField'),
),
body: Container(
padding: const EdgeInsets.all(20.0),
child: TextFormField(
keyboardType: TextInputType.text,
controller: passwordController,
obscureText: !obscureText,
decoration: const InputDecoration(
hintText: 'Password',
prefixIcon: Icon(Icons.lock_open),
suffixIcon: IconButton(
icon: Icon(obscureText
? Icons.visibility
: Icons.visibility_off),
onPressed: () {
setState(() {
obscureText = !obscureText;
});
}),
),
validator: (value) {
if (value!.isEmpty) {
return 'Enter password';
}
return null;
},
),
)));
}
}
You cant create const InputDecoration because the icon and onPressed is depended/changes on run time.
Remove the const before decoration: InputDecoration(
decoration: InputDecoration(
hintText: 'Password',
prefixIcon: const Icon(Icons.lock_open),
suffixIcon: IconButton(
icon: Icon(obscureText
? Icons.visibility
: Icons.visibility_off),
onPressed: () {
setState(() {
obscureText = !obscureText;
});
}),
),
Try the following code:
import 'package:flutter/material.dart';
void main() {
runApp(const RunMyApp());
}
class RunMyApp extends StatefulWidget {
const RunMyApp({super.key});
#override
State<RunMyApp> createState() => _RunMyAppState();
}
class _RunMyAppState extends State<RunMyApp> {
bool passwordVisible = false;
final passwordController = TextEditingController();
bool obscureText = false;
#override
void initState() {
super.initState();
passwordVisible = true;
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(primarySwatch: Colors.green),
home: Scaffold(
appBar: AppBar(
title: const Text('Show or Hide Password in TextField'),
),
body: Container(
padding: const EdgeInsets.all(20.0),
child: TextFormField(
keyboardType: TextInputType.text,
controller: passwordController,
obscureText: !obscureText,
decoration: InputDecoration(
hintText: 'Password',
prefixIcon: const Icon(Icons.lock_open),
suffixIcon: IconButton(
icon: Icon(obscureText ? Icons.visibility : Icons.visibility_off),
onPressed: () {
setState(() {
obscureText = !obscureText;
});
},
),
),
validator: (value) {
if (value!.isEmpty) {
return 'Enter password';
}
return null;
},
),
),
),
);
}
}
I am facing one strange issue in the flutter progressive web application. It's working well in safari and chrome browsers. It's creating an issue when we add it to the home screen. We are having only two text fields on the page and nothing else. After opening a keyboard and clicking on the done or return button then we tap outside the TextInput area multiple times(5 - 6 times) then the canvas(body) of the page reduces gradually. Please check the attached video for it. Video Link
Please check below code:
import 'package:demo_texfield_web/unfocser.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: TextfieldDemo(),
);
}
}
class TextfieldDemo extends StatefulWidget {
const TextfieldDemo({Key? key}) : super(key: key);
#override
State<TextfieldDemo> createState() => _TextfieldDemoState();
}
class _TextfieldDemoState extends State<TextfieldDemo> {
var txtxField1 = TextEditingController();
var txtxField2 = TextEditingController();
FocusNode _focusNode1 = new FocusNode();
FocusNode _focusNode2 = new FocusNode();
final _formKey = GlobalKey<FormState>();
int count = 0;
#override
void initState(){
super.initState();
_focusNode1.addListener(_focusNodeListener);
}
#override
void dispose(){
_focusNode1.removeListener(_focusNodeListener);
super.dispose();
}
Future<Null> _focusNodeListener() async {
if (_focusNode1.hasFocus){
print('TextField got the focus');
} else {
print('TextField lost the focus');
FocusScope.of(context).unfocus();
}
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context);
if(!currentFocus.hasPrimaryFocus) {
currentFocus.focusedChild!.unfocus();
}
},
child: Scaffold(
body:Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.all(60.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Unfocuser(
child: TextFormField(
decoration: const InputDecoration(
border: UnderlineInputBorder(),
filled: true,
icon: Icon(Icons.person),
hintText: 'Enter your first name',
labelText: 'First name *',
),
onSaved: (String? value) {
//TODO
},
controller: txtxField1,
focusNode: _focusNode1,
),
),
const SizedBox(height: 25,),
Unfocuser(
child: TextFormField(
keyboardType: TextInputType.number,
decoration: const InputDecoration(
border: UnderlineInputBorder(),
filled: true,
icon: const Icon(Icons.person),
hintText: 'Enter your Last name',
labelText: 'Last name *',
),
onSaved: (String? value) {
//TODO
},
controller: txtxField2,
focusNode: _focusNode2,
),
),
],
),
),
),
),
);
}
}
class PasswordTextField extends StatefulWidget {
final String hintText;
final IconData icon;
final TextEditingController controller;
final FormFieldValidator<String> validator;
PasswordTextField({
Key key,
this.hintText ,
this.icon = Icons.lock,
this.validator,
this.controller
}) : super(key: key);
#override
_PasswordTextFieldState createState() => _PasswordTextFieldState();
}
class _PasswordTextFieldState extends State<PasswordTextField> {
var _passwordVisible;
var _iconColor;
#override
void initState() {
_passwordVisible = true;
_iconColor = Colors.grey;
}
#override
Widget build(BuildContext context) {
// TODO: implement build
return TextFieldContainer(
child: TextFormField(
controller: controller, //here
validator: validator, //here
obscureText: _passwordVisible,
cursorColor: kPrimaryightColor,
decoration: InputDecoration(
labelText: "Your Password",
labelStyle: TextStyle(color: kPrimaryColor) ,
hintText: hintText, /ere
border: InputBorder.none,
icon: Icon(
icon, //here
color: kPrimaryColor,
),
suffixIcon: IconButton(
icon: Icon(Icons.remove_red_eye),
color: _iconColor,
onPressed: (){
setState(() {
if(_passwordVisible == true){
_passwordVisible = false;
_iconColor = kPrimaryColor;
}else{
_passwordVisible = true;
_iconColor = Colors.grey;
}
});
},
),
),
),
);
}
#override
State<StatefulWidget> createState() {
// TODO: implement createState
throw UnimplementedError();
}
}
I want to access some attribute from my stateful widget, but I don't know how, it work like this in stateless, is there any another way to use this on another file?
I use it like this
PasswordTextField(
validator:(value){
if(value.isEmpty){
return "Please insert something";
}else if(value.length < 6){
return "Enter Correct Password Format (6 character)";
}else{
return null;
}
You can access the fields declared in your Stateful widget class in the state class by using the predefined field widget i.e. widget.controller. So your code will look like this:
#override
Widget build(BuildContext context) {
return TextFieldContainer(
child: TextFormField(
controller: widget.controller, // here
validator: widget.validator, // here
obscureText: _passwordVisible,
cursorColor: kPrimaryightColor,
decoration: InputDecoration(
labelText: "Your Password",
labelStyle: TextStyle(color: kPrimaryColor) ,
hintText: widget.hintText, // here
border: InputBorder.none,
icon: Icon(
widget.icon, // here
color: kPrimaryColor,
),
// Define other controls
),
),
);
}
I want disable a button while I'm typing on input.
But the code below that I 've wrote doesn't work because the button is disabled only when I "confirm" input with keyboard, but I want disabled input while I'm typing on input.
TextEditingController myController = TextEditingController();
bool isValid = false;
#override
Widget build(BuildContext context) {
Column(
children: <Widget>[
TextField(
controller: myController,
onChanged: (value){
setState(() {
isValid = (value.isEmpty || double.tryParse(value) == null) ? false : true;
});
},
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Enter a search term'
),
),
RaisedButton(
disabledColor: Colors.grey,
child: Text("${AppLocalizations.of(context).translate("test")}"),
onPressed: isValid ? () { print("test") }:null,
),
],
)
}
You can Also use myController.addListener()
To check result just copy paste below code in DartPad
When you enter number in TextField the button will enable
SAMPLE CODE
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController myController = TextEditingController();
bool isValid = false;
#override
void dispose() {
// Clean up your controller when the Widget is disposed
myController.dispose();
super.dispose();
}
#override
void initState() {
// TODO: implement initState
super.initState();
myController.text = '';
myController.addListener((){
print("Get Value: ${myController.text}");
setState(() {
isValid = (myController.text.isEmpty || double.tryParse(myController.text) == null)
? false
: true;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: <Widget>[
TextField(
controller: myController,
onChanged: (value) {
setState(() {
});
},
decoration: InputDecoration(
border: InputBorder.none, hintText: 'Enter a search term'),
),
RaisedButton(
disabledColor: Colors.grey,
child: Text("Click Me"),
onPressed: isValid
? () {
print("test");
}
: null,
),
],
),
);
}
}
Use FocusNode
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: DemoPage(),
debugShowCheckedModeBanner: false,
theme: ThemeData(primaryColor: Colors.white),
);
}
}
class DemoPage extends StatefulWidget {
#override
_DemoPageState createState() => _DemoPageState();
}
class _DemoPageState extends State<DemoPage> {
TextEditingController textField1Ctrl;
TextEditingController textField2Ctrl;
FocusNode focusNode1;
FocusNode focusNode2;
#override
void initState() {
textField1Ctrl = TextEditingController();
textField2Ctrl = TextEditingController();
focusNode1 = FocusNode()..addListener(_rebuildOnFocusChange);
focusNode2 = FocusNode()..addListener(_rebuildOnFocusChange);
super.initState();
}
void _rebuildOnFocusChange() => setState(() {});
void _onButton1Pressed() {}
void _onButton2Pressed() {}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("Disable Button When Text Field has focus"),
Row(
children: <Widget>[
Expanded(
child: TextField(
controller: textField1Ctrl,
focusNode: focusNode1,
),
),
RaisedButton(
child: Text("Button 1"),
onPressed: focusNode1.hasFocus ? null : _onButton1Pressed,
)
],
),
const SizedBox(height: 40.0),
Text("Disable Button When TextField is Empty or has focus"),
Row(
children: <Widget>[
Expanded(
child: TextField(
controller: textField2Ctrl,
focusNode: focusNode2,
),
),
RaisedButton(
child: Text("Button 2"),
onPressed: focusNode2.hasFocus || textField2Ctrl.text.isEmpty
? null
: _onButton2Pressed,
)
],
),
],
),
),
);
}
}
Demo: DartPad
When I use TextInputAction and set it to next, the button does change on my simulator device however it doesn't do anything, User interaction is not moved into the next element.
Have opened a ticket on the FLutter `gitHUb page as well as in the chat rooms but no help so far and would like to keep the ball rolling on my training :)
https://github.com/flutter/flutter/issues/47749
There is bug in your code , you put _passwordFocusNode in email field and cause error
when _emailEditingComplete() , focus stay in email
void _emailEditingComplete() {
FocusScope.of(context).requestFocus(_passwordFocusNode);
}
return TextField(
controller: _passwordController,
focusNode: _emailFocusNode,
return TextField(
controller: _emailController,
focusNode: _passwordFocusNode,
onEditingComplete and onSubmitted both work correctly in this case
working demo for test
full test code
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
final FocusNode _emailFocusNode = FocusNode();
final FocusNode _passwordFocusNode = FocusNode();
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
void dispose() {
// Clean up the focus node when the Form is disposed.
_emailFocusNode.dispose();
_passwordFocusNode.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
focusNode: _emailFocusNode,
decoration: InputDecoration(
labelText: 'Email',
hintText: 'test#test.com',
),
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.next,
onEditingComplete: () {
FocusScope.of(context).requestFocus(_passwordFocusNode);
},
onSubmitted: (val) {
//FocusScope.of(context).requestFocus(_passwordFocusNode);
},
),
TextField(
focusNode: _passwordFocusNode,
decoration: InputDecoration(
labelText: 'password',
),
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.done,
onSubmitted: (val) {},
),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
bug