Reputation: 135
I have created a login screen for my app but in password field I want a functionality like when I type password its been in * format and in right side a icon on when user click on it, password will be visible, I created a code for it but when I click on password field that icon getting invisible and when password field loose focus that icon appearing again, then how to always show that icon even password field is in focus? I have provided a snapshot to easily understand the problem.
Here are my login screen code....
import 'package:flutter/material.dart';
import 'package:email_validator/email_validator.dart';
import 'package:secret_keeper/screens/home_screen/Home.dart';
import 'package:secret_keeper/screens/home_screen/passwords/PasswordsNavigation.dart';
import 'package:secret_keeper/screens/signup_page/SignupPage.dart';
class LoginPage extends StatefulWidget{
@override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
String _emailID, _password = "",_email = "[email protected]", _pass = "Try.t.r.y@1";
bool _obscureText = true;
final _formKey = GlobalKey<FormState>();
void _toggle(){
setState(() {
_obscureText = !_obscureText;
});
}
void validateLogin(){
if(_formKey.currentState.validate()){
_formKey.currentState.save();
if(_emailID == _email && _password == _pass){
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => Home()));
}
}
}
Widget emailInput(){
return TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: "Email ID",
labelStyle: TextStyle(fontSize: 14,color: Colors.grey.shade400),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(
color: Colors.grey.shade300,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(
color: Colors.red,
)
),
),
validator: (email) {
if (email.isEmpty)
return 'Please Enter email ID';
else if (!EmailValidator.validate(email))
return 'Enter valid email address';
else
return null;
},
onSaved: (email)=> _emailID = email,
textInputAction: TextInputAction.next,
);
}
Widget passInput(){
return TextFormField(
keyboardType: TextInputType.text,
decoration: InputDecoration(
labelText: "Password",
labelStyle: TextStyle(fontSize: 14,color: Colors.grey.shade400),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(
color: Colors.grey.shade300,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(
color: Colors.red,
)
),
suffixIcon: IconButton(
icon: Icon(
_obscureText ? Icons.visibility : Icons.visibility_off,
),
onPressed: _toggle,
),
),
validator: (password){
Pattern pattern =
r'^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[!@#\$&*~]).{8,}$';
RegExp regex = new RegExp(pattern);
if (password.isEmpty){
return 'Please Enter Password';
}else if (!regex.hasMatch(password))
return 'Enter valid password';
else
return null;
},
onSaved: (password)=> _password = password,
textInputAction: TextInputAction.done,
obscureText: _obscureText,
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false,
backgroundColor: Colors.white,
body: SafeArea(
child: Container(
padding: EdgeInsets.only(left: 16,right: 16),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(height: 50,),
Text("Welcome,",style: TextStyle(fontSize: 26,fontWeight: FontWeight.bold),),
SizedBox(height: 6,),
Text("Sign in to continue!",style: TextStyle(fontSize: 20,color: Colors.grey.shade400),),
],
),
Column(
children: <Widget>[
emailInput(),
SizedBox(height: 16,),
passInput(),
SizedBox(height: 12,),
Align(
alignment: Alignment.topRight,
child: Text("Forgot Password ?",style: TextStyle(fontSize: 14,fontWeight: FontWeight.w600),),
),
SizedBox(height: 30,),
Container(
height: 50,
width: double.infinity,
child: FlatButton(
onPressed: validateLogin,
padding: EdgeInsets.all(0),
child: Ink(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6),
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
Color(0xffff5f6d),
Color(0xffff5f6d),
Color(0xffffc371),
],
),
),
child: Container(
alignment: Alignment.center,
constraints: BoxConstraints(maxWidth: double.infinity,minHeight: 50),
child: Text("Login",style: TextStyle(color: Colors.white,fontWeight: FontWeight.bold),textAlign: TextAlign.center,),
),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6),
),
),
),
SizedBox(height: 16,),
Container(
height: 50,
width: double.infinity,
child: FlatButton(
onPressed: (){},
color: Colors.indigo.shade50,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.asset("assets/images/facebook.png",height: 18,width: 18,),
SizedBox(width: 10,),
Text("Connect with Facebook",style: TextStyle(color: Colors.indigo,fontWeight: FontWeight.bold),),
],
),
),
),
SizedBox(height: 16,),
Container(
height: 50,
width: double.infinity,
child: FlatButton(
onPressed: (){},
color: Colors.indigo.shade50,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.asset("assets/images/facebook.png",height: 18,width: 18,),
SizedBox(width: 10,),
Text("Connect with Facebook",style: TextStyle(color: Colors.indigo,fontWeight: FontWeight.bold),),
],
),
),
),
],
),
Padding(
padding: EdgeInsets.only(bottom: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("Don't have an account?",style: TextStyle(fontWeight: FontWeight.bold),),
SizedBox(width: 5,),
GestureDetector(
onTap: (){
Navigator.push(context, MaterialPageRoute(builder: (context){
return SignupPage();
}));
},
child: Text("Sign up",style: TextStyle(fontWeight: FontWeight.bold,color: Colors.red),),
)
],
),
)
],
),
),
),
),
);
}
}
Upvotes: 1
Views: 11760
Reputation: 330
Full Example.main login here is:
below i gave a full example for the task.
bool _passwordInVisible = true; //a boolean value
TextFormField buildPasswordFormField() {
return TextFormField(
obscureText: _passwordInVisible,
onSaved: (newValue) => registerRequestModel.password = newValue,
onChanged: (value) {
if (value.isNotEmpty) {
removeError(error: kPassNullError);
} else if (value.length >= 8) {
removeError(error: kShortPassError);
}
return null;
},
validator: (value) {
if (value.isEmpty) {
addError(error: kPassNullError);
return "";
} else if (value.length < 8) {
addError(error: kShortPassError);
return "";
}
return null;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "Password",
hintText: "Enter your password",
contentPadding: new EdgeInsets.symmetric(vertical: 5.0, horizontal: 15.0),
floatingLabelBehavior: FloatingLabelBehavior.always,
suffixIcon: IconButton(
icon: Icon(
_passwordInVisible ? Icons.visibility_off : Icons.visibility, //change icon based on boolean value
color: Theme.of(context).primaryColorDark,
),
onPressed: () {
setState(() {
_passwordInVisible = !_passwordInVisible; //change boolean value
});
},
),
),
);
}
Upvotes: 3
Reputation: 119
Here two scenarios come
button for password show hide
var passShowButton = GestureDetector(
onLongPressEnd: outContact,
onTapDown: inContact, //call this method when incontact
onTapUp:
outContact, //call this method when contact with screen is removed
child: Icon(
getXHelper.isEmailPasswordUpdate.isTrue
? AppIcons.hidePassword
: AppIcons.hidePassword,
size: 18,
color:Colors.grey
),
);
TextField
TextField(
obscureText: getXHelper.isPassInvisible ,
autocorrect: false,
textAlignVertical: TextAlignVertical.bottom,
decoration: InputDecoration(
enabled: true,
errorBorder: UnderlineInputBorder(
borderSide: BorderSide(color: AppColors.primary)),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: AppColors.primary)),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: AppColors.primary)),
border: UnderlineInputBorder(
borderSide: BorderSide(color: AppColors.primary)),
fillColor: Colors.white,
filled: true,
isDense: true,
prefixIconConstraints: BoxConstraints(maxHeight: 18, minHeight: 18),
hintText: "Password",
prefixIcon: Padding(
padding: const EdgeInsets.only(top: 0, right: 12, bottom: 0),
child: Icon(Icons.lock, size: 18, color: Colors.grey),
),
suffixIcon: passShowButton,
),
cursorColor: Colors.black,
style: TextStyle(
color: Colors.black, fontFamily: AppFontFamily.fontFamily),
)
Password show hide button
var passShowButton = GestureDetector(
onLongPressEnd: outContact,
onTapDown: inContact, //call this method when incontact
onTapUp:
outContact, //call this method when contact with screen is removed
child: Icon(
getXHelper.isEmailPasswordUpdate.isTrue
? AppIcons.hidePassword
: AppIcons.hidePassword,
size: 18,
),
);
TextField(
obscureText: getXHelper.isPassInvisible ,
autocorrect: false,
textAlignVertical: TextAlignVertical.bottom,
decoration: InputDecoration(
enabled: true,
errorBorder: UnderlineInputBorder(
borderSide: BorderSide(color: AppColors.primary)),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: AppColors.primary)),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: AppColors.primary)),
border: UnderlineInputBorder(
borderSide: BorderSide(color: AppColors.primary)),
fillColor: Colors.white,
filled: true,
isDense: true,
prefixIconConstraints: BoxConstraints(maxHeight: 18, minHeight: 18),
hintText: "Password",
prefixIcon: Padding(
padding: const EdgeInsets.only(top: 0, right: 12, bottom: 0),
child: Icon(Icons.lock, size: 18),
),
suffixIcon: passShowButton,
),
cursorColor: Colors.black,
style: TextStyle(
color: Colors.black, fontFamily: AppFontFamily.fontFamily),
)
Upvotes: 1
Reputation: 135
Actually, the suffix icon is visible but when i click on TextFormField then the icon color is changing to white so simply in icon field i added a color property and give a black color to icon so even textfield is in focus its color remain black.
Upvotes: 0
Reputation: 4098
I just copied and run your code and it works just fine. The icon was visible when the password field had focus. You should maybe check your flutter version or it might probably be your emulator device.
flutter --version
Flutter 1.22.3 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 8874f21e79 (2 weeks ago) • 2020-10-29 14:14:35 -0700
Engine • revision a1440ca392
Tools • Dart 2.10.3
Upvotes: 0
Reputation: 1741
you can put text field and icon button in a stack replace this code with your password textfield. you can change icon button position to what you want.
Stack(
children: [
TextFormField(
keyboardType: TextInputType.text,
decoration: InputDecoration(
labelText: "Password",
labelStyle:
TextStyle(fontSize: 14, color: Colors.grey.shade400),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(
color: Colors.grey.shade300,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(
color: Colors.red,
)),
),
validator: (password) {
Pattern pattern =
r'^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[!@#\$&*~]).{8,}$';
RegExp regex = new RegExp(pattern);
if (password.isEmpty) {
return 'Please Enter Password';
} else if (!regex.hasMatch(password))
return 'Enter valid password';
else
return null;
},
onSaved: (password) => _password = password,
textInputAction: TextInputAction.done,
obscureText: _obscureText,
),
Positioned(
top: 2,
right: 10,
child: IconButton(
icon: Icon(
_obscureText ? Icons.visibility : Icons.visibility_off,
),
onPressed: () {
setState(() {
_obscureText = !_obscureText;
});
}),
),
],
),
Upvotes: 0