I try to use FocusNode() in TextFormField so it will detect when I focus on the TextFormField, the text above will have it’s color changed. But it seems not working, what seems to be the problem?
enter image description here
import 'package:flutter/material.dart';
class SignIn extends StatefulWidget {
const SignIn({Key? key}) : super(key: key);
@override
_SignInState createState() => _SignInState();
}
class _SignInState extends State<SignIn> {
bool isPasswordVisible = false;
bool _isEmail = true;
bool _isPassword = true;
TextEditingController emailInput = TextEditingController();
TextEditingController passwordInput = TextEditingController();
FocusNode emailText = FocusNode();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: SingleChildScrollView(
child: Container(
padding: EdgeInsets.all(30.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Sign In to Coinify',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 24.0,
fontFamily: "Graphik",
)
),
SizedBox(height: 20.0),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Email',
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 16.0,
color: emailText.hasFocus ? Colors.blue : Colors.black,
fontFamily: "Graphik",
),
),
SizedBox(height: 8.0),
TextFormField(
focusNode: emailText,
controller: emailInput,
decoration: InputDecoration(
contentPadding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
border: OutlineInputBorder(),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey)
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue)
),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.red),
),
focusedErrorBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.red)
),
hintText: 'Enter your email',
errorText: _isEmail ? null : "Email must not be empty",
),
)
],
),
SizedBox(height: 20.0),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Password',
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 16.0,
fontFamily: "Graphik",
),
),
SizedBox(height: 8.0),
TextFormField(
controller: passwordInput,
obscureText: !isPasswordVisible,
decoration: InputDecoration(
contentPadding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
border: OutlineInputBorder(),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey)
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue)
),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.red),
),
focusedErrorBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.red),
),
hintText: 'Enter your password',
errorText: _isPassword ? null : "Password must not be empty",
suffixIcon: GestureDetector(
onTap: () {
setState(() {
isPasswordVisible = !isPasswordVisible;
});
},
child: Icon(
isPasswordVisible ? Icons.visibility : Icons.visibility_off,
),
),
),
)
],
),
SizedBox(height: 50.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: () {
Navigator.pushNamed(context, '/forgot-password');
},
child: Text(
'Forgot password?',
style: TextStyle(
color: Colors.blue,
)
)
)
),
MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: () {
Navigator.pushNamed(context, '/privacy-policy');
},
child: Text(
'Privacy policy',
style: TextStyle(
color: Colors.blue,
)
)
)
),
]
),
SizedBox(height: 20.0),
ElevatedButton(
onPressed: () {
setState(() {
if(emailInput.text == ""){_isEmail = false;}
else{_isEmail = true;}
if(passwordInput.text == ""){_isPassword = false;}
else{_isPassword = true;}
if(_isEmail && _isPassword) {Navigator.pushNamed(context, '/sign-in-code');}
});
},
child: Text(
"Sign in",
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.normal,
color: Colors.white
),
),
style: ButtonStyle(
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0))
),
minimumSize: MaterialStateProperty.all(Size.fromHeight(60.0)),
backgroundColor: MaterialStateProperty.all(Colors.blue),
shadowColor: MaterialStateProperty.all(Colors.transparent)
),
)
]
)
),
)
);
}
}
I have tried to change the color in the ternary operator and realized that the Color seems to stuck in false value
4
Answers
The state is not changing when the focus is changed, therefore the text color doesn’t change.
You must listen to the
FocusNode
changes andsetState
after any changes. Update your widget like this:Use
_emailTextColor
as your text color insideTextStyle
.You should add a listener to focusNode value to detect where the TextFormField is being focused or not.
I prefer to use ValueNotifier and ValueListenableBuilder to rebuild only the Text widget not all the widgets in the screen.
In Build method I wrapped the Email Text Widget with ValueListenableBuilder widget to rebuild the widget if the emailInput is focused.
You may add the
setState
method as alistener
to theFocusNode
object namedemailText
. This will change the color of the Text you want to change based on the focus on the TextField.Modified code:
The problem is because your UI is not rebuild when you focus the TextField.
You must call the
setState()
to update your UI.Method 1: Using your existing
FocusNode
Since you have already creating the focus node and set color in the ternary operator, you just need to add the following code:
And this is your final code:
Method 2: Using
Focus
widgetThe second method is more simple, it just only wrap your
TextFormField
withFocus
widget and call thesetState
in theonFocusChange
like below:And this is your final code using this method:
And this is the result:
Hopefully it can solve your problem, Thanks 😉