Related
How do I properly align the prefix icon, the hintText, the actual value that the user has typed in and the suffix icon? I am using textformfield for this one.
Widget yourNameWidget(yourNameCtrlr) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 0.0),
child: TextFormField(
style: const TextStyle(fontFamily: 'Poppins', fontSize: 12),
controller: yourNameCtrlr,
keyboardType: TextInputType.text,
decoration: InputDecoration(
contentPadding: EdgeInsets.all(18),
isDense: true,
prefixIcon: const Icon(Icons.person),
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Color(0xFFCECECE)),
borderRadius: BorderRadius.circular(12),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: const BorderSide(color: Color(0xFFCECECE)),
),
// this does not align with the prefix and the hint text
suffix: GestureDetector(
onTap: () {
yourNameCtrlr.clear();
},
child: const Icon(
Icons.clear,
size: 16,
),
),
hintText: 'Your Name',
fillColor: const Color(0xFFFEFEFE),
filled: true,
),
validator: (value) {
if (value!.isEmpty || !RegExp(r'^[a-z A-Z]+$').hasMatch(value)) {
return "Please enter a valid name.";
} else {
return null;
}
},
onChanged: (value) {},
),
);
}
I want the three of it (prefix,hint text, suffix) should be aligned.
Here is the image for the preview of the textformfield
https://prnt.sc/BxYxnZx1G5od
I was used this type of textformfield please see the reference below:
TextFormField(
controller: textEditingController,
cursorColor: AppTheme.secondaryColor,
autofocus: true,
onChanged: (txt) {
},
style: const TextStyle(
fontSize: 16.0, color:
Color.fromARGB(255,4,4,4)),
decoration: InputDecoration(
border: InputBorder.none,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(
color: AppTheme.secondaryColor_30,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(
color: AppTheme.secondaryColor_30,
),
),
hintText:
StringConstants.searchForAGroupOrFriend,
hintStyle: Theme.of(context)
.textTheme
.caption!
.copyWith(color: AppTheme.grey2),
fillColor: AppTheme.secondaryColor_10,
contentPadding: const EdgeInsets.only(top: 10),
filled: true,
prefixIcon: GestureDetector(
onTap: () {
},
child: Image.asset(
Assets.icBackRound,
scale: 3.5,
color: AppTheme.backDarkGrey,
),
),
suffixIcon: GestureDetector(
child: Image.asset(
Assets.searchIcon,
color: AppTheme.secondaryColor,
scale: 3.5,
),
onTap: () {
},
),
),
),
how do i make the textfield shorter and not goes behind the clear button?
Stack(
alignment: AlignmentDirectional.centerEnd,
children: [
TextField(
textInputAction: TextInputAction.search,
controller: controller,
focusNode: focusNode,
autofocus: true,
onChanged: (text) {
text.length >= 4
? provider.fetchBySearchName(text)
: buildNoData();
},
decoration: InputDecoration(
labelText: 'Search',
labelStyle: TextStyle(color: Colors.white),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(width: 2, color: Theme.of(context).primaryColor),
// borderRadius: BorderRadius.circular(10),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(width: 2, color: Theme.of(context).primaryColor),
// borderRadius: BorderRadius.circular(10),
)
),
),
IconButton(
onPressed: clearText,
color: Theme.of(context).primaryColor,
icon: Icon(Icons.cancel_outlined)
)
],
),
Try below code and use suffixIcon for text overlapping issue
TextFormField(
decoration: InputDecoration(
labelText: 'Search',
hintText: 'Search Here',
suffixIcon: IconButton(
onPressed: () {
print('Button Pressed');
//put your clear function here
},
icon: Icon(
Icons.cancel_outlined,
),
),
/*suffixIcon: InkWell(
onTap: () {
print('Button Pressed');
//put your clear function here
},
child: Icon(
Icons.cancel_outlined,
),
),*/
border: OutlineInputBorder(),
),
),
Result
put IconButton on suffixIcon.
TextField(
textInputAction: TextInputAction.search,
controller: controller,
focusNode: focusNode,
autofocus: true,
onChanged: (text) {
text.length >= 4
? provider.fetchBySearchName(text)
: buildNoData();
},
decoration: InputDecoration(
suffixIcon: IconButton(
onPressed: clearText,
color: Theme.of(context).primaryColor,
icon: Icon(Icons.cancel_outlined)
),
labelText: 'Search',
labelStyle: TextStyle(color: Colors.white),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(width: 2, color: Theme.of(context).primaryColor),
// borderRadius: BorderRadius.circular(10),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(width: 2, color: Theme.of(context).primaryColor),
// borderRadius: BorderRadius.circular(10),
)
),
),
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 = "abc#gmail.com", _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),),
)
],
),
)
],
),
),
),
),
);
}
}
Full Example.main login here is:
take a boolean param for detecting if text is obscure or not
change suffix icon based on that boolean value
change the boolean value on suffix item click
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
});
},
),
),
);
}
Here two scenarios come
If you want your suffix icon color constant like always grey, you can give color property of icon, like :
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),
)
If you want your suffix icon color of your app-Primary Color, will change color when textfield focus, like :
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),
)
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;
});
}),
),
],
),
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
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.
This the main screen and on it i have the AuthCard widget that i use to switch between Login and Signup.
import 'package:Zabatnee/common_app/provider/auth_provider.dart';
import 'package:Zabatnee/common_app/widgets/auth_card.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class SignupScreen extends StatefulWidget {
static const routeName = '/signUpScreen';
#override
_SignupScreenState createState() => _SignupScreenState();
}
class _SignupScreenState extends State<SignupScreen> {
var isVerified = true;
var isInit = true;
var _isLogin = true;
#override
void didChangeDependencies() {
if(isInit){
isVerified = Provider.of<AuthProvider>(context, listen: false).isVerified;
}
isInit = false;
super.didChangeDependencies();
}
#override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
return Stack(
children: <Widget>[
Container(
height: deviceSize.height,
width: deviceSize.width,
child: Image.asset(
'assets/Images/Login-bg.png',
fit: BoxFit.cover,
),
),
Container(
color: Color.fromRGBO(224, 254, 240, 1).withOpacity(.5),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Flexible(
child: Container(
margin: EdgeInsets.all(35),
padding:
EdgeInsets.symmetric(vertical: 8, horizontal: 70),
// transform: Matrix4.rotationZ(-8 * pi / 180)
// ..translate(-10.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Theme.of(context).accentColor,
boxShadow: [
BoxShadow(blurRadius: 8, offset: Offset(0, 2))
]),
child: Image.asset(
'assets/Images/zabatnee_logo.png',
fit: BoxFit.cover,
),
),
),
Container(
height: _isLogin ? deviceSize.height*.35 :deviceSize.height*.6,
child: AuthCard(isVerified),)
],
),
],
);
}
}
and below the widget which contain a boolean (_isLogin), what i need is when i choose login the height of card to be deviceSize.height*.35 and when i use Signup to be deviceSize.
#override
Widget build(BuildContext context) {
final deviceSize = MediaQuery.of(context).size;
return Container(
width: deviceSize.width * .85,
child: Column(
children: <Widget>[
Expanded(
child: Card(
color: Colors.black54,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
elevation: 8,
child: Container(
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
children: <Widget>[
if (!_isLogin)
TextFormField(
key: ValueKey('first name'),
style: TextStyle(color: Colors.white),
textInputAction: TextInputAction.next,
onFieldSubmitted: (_) {
FocusScope.of(context)
.requestFocus(_lastNameFocusNode);
},
autofocus: false,
validator: (value) {
if (value.isEmpty) {
return 'please enter your first name';
}
return null;
},
onSaved: (value) {
_signupModel.firstName = value;
},
decoration: InputDecoration(
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
border: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
focusColor: Theme.of(context).primaryColor,
hintText: 'Please enter your First Name ...',
hintStyle: TextStyle(color: Colors.white24),
labelText: 'First Name',
labelStyle: TextStyle(color: Colors.white),
),
keyboardType: TextInputType.text,
),
if (!_isLogin)
TextFormField(
key: ValueKey('Last Name'),
style: TextStyle(color: Colors.white),
textInputAction: TextInputAction.next,
decoration: InputDecoration(
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
border: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
focusColor: Theme.of(context).primaryColor,
hintText: 'Please enter your Last Name ...',
hintStyle: TextStyle(color: Colors.white24),
labelText: 'Last Name',
labelStyle: TextStyle(color: Colors.white),
),
keyboardType: TextInputType.text,
focusNode: _lastNameFocusNode,
validator: (value) {
if (value.isEmpty) {
return 'please enter your last name';
}
return null;
},
onFieldSubmitted: (_) {
FocusScope.of(context)
.requestFocus(_emailFocusNode);
},
onSaved: (value) {
//_signupModel = SignUpModel(firstName: _signupModel.firstName, lastName: value,email: _signupModel.email, mobile: _signupModel.mobile, password: _signupModel.password, countryCode: _signupModel.countryCode, gender: _signupModel.gender,sms: _signupModel.sms);
_signupModel.lastName = value;
},
),
TextFormField(
key: ValueKey('email'),
autofocus: false,
style: TextStyle(color: Colors.white),
textInputAction: TextInputAction.next,
focusNode: _emailFocusNode,
onFieldSubmitted: (_) {
FocusScope.of(context)
.requestFocus(_phoneFocusScope);
},
onSaved: (value) {
_signupModel.email = value;
},
decoration: _isLogin
? InputDecoration(
prefixIcon: Icon(
Icons.person,
color: Colors.white,
),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
border: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
focusColor: Theme.of(context).primaryColor,
hintText: 'Please enter your email...',
hintStyle: TextStyle(color: Colors.white24),
labelText: 'Email',
labelStyle: TextStyle(color: Colors.white),
)
: InputDecoration(
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
border: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
focusColor: Theme.of(context).primaryColor,
hintText: 'Please enter your email...',
hintStyle: TextStyle(color: Colors.white24),
labelText: 'Email',
labelStyle: TextStyle(color: Colors.white),
),
validator: (value) {
if (!validator.isEmail(value)) {
return 'please enter a valid email';
}
return null;
},
keyboardType: TextInputType.emailAddress,
),
if (!_isLogin)
Row(
children: <Widget>[
Container(
child: CountryCodePicker(
onInit: (code) {
_signupModel.countryCode = '+20';
},
onChanged: (code) {
_signupModel.countryCode = code.toString();
},
initialSelection: 'EG',
textStyle: TextStyle(color: Colors.white),
padding: EdgeInsets.only(right: 8, left: 8),
),
),
Expanded(
child: TextFormField(
key: ValueKey('phone number'),
autofocus: false,
decoration: InputDecoration(
enabledBorder: UnderlineInputBorder(
borderSide:
BorderSide(color: Colors.white),
),
focusedBorder: UnderlineInputBorder(
borderSide:
BorderSide(color: Colors.white),
),
border: UnderlineInputBorder(
borderSide:
BorderSide(color: Colors.white),
),
hintText:
'Please enter your Phone Number...',
hintStyle: TextStyle(color: Colors.white24),
labelText: 'Phone Number',
labelStyle: TextStyle(color: Colors.white),
),
keyboardType: TextInputType.phone,
style: TextStyle(color: Colors.white),
textInputAction: TextInputAction.next,
focusNode: _phoneFocusScope,
onFieldSubmitted: (_) {
FocusScope.of(context)
.requestFocus(_passwordFocusNode);
},
maxLength: 10,
validator: (value) {
if (value.length != 10) {
return 'please enter a valid phone number';
}
return null;
},
onSaved: (value) {
_signupModel.mobile = value;
},
),
),
],
),
TextFormField(
key: ValueKey('password'),
style: TextStyle(color: Colors.white),
textInputAction: TextInputAction.done,
onFieldSubmitted: (_) {},
onSaved: (value) {
_signupModel.password = value;
},
focusNode: _passwordFocusNode,
obscureText: _showPassword ? false : true,
decoration: _isLogin
? InputDecoration(
suffixIcon: GestureDetector(
onTap: () {
_togglevisibility();
},
child: Icon(_showPassword
? Icons.visibility
: Icons.visibility_off),
),
prefixIcon: Icon(
Icons.lock,
color: Colors.white,
),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
border: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
hintText: 'Please enter your password...',
hintStyle: TextStyle(color: Colors.white24),
labelText: 'Password',
labelStyle: TextStyle(color: Colors.white),
)
: InputDecoration(
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
border: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
hintText: 'Please enter your password...',
hintStyle: TextStyle(color: Colors.white24),
labelText: 'Password',
labelStyle: TextStyle(color: Colors.white),
),
validator: (value) {
if (value.length < 6) {
return 'please enter password lager that 6 character';
}
return null;
},
keyboardType: TextInputType.visiblePassword,
),
SizedBox(
height: 20,
),
if (!_isLogin)
Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Date Of Birth',
style: TextStyle(
color: Colors.white,
fontSize: 16,
),
),
Row(
children: <Widget>[
IconButton(
icon: Icon(
Icons.date_range,
color: Colors.white,
),
onPressed: () {
_selectDateOfBirth(context);
_removeFocus();
}),
FlatButton(
onPressed: () {
_selectDateOfBirth(context);
_removeFocus();
},
child: Text(
formatted == null
? 'No Date Choosen!'
: formatted,
style: TextStyle(
color: Colors.white, fontSize: 16),
),
)
],
)
],
),
),
SizedBox(
height: 20,
),
if (!_isLogin)
Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text(
'Gender',
style: TextStyle(
color: Colors.white,
fontSize: 16,
),
),
RadioListTile(
value: 'Male',
activeColor: Theme.of(context).primaryColor,
groupValue: selectedRadioTile,
onChanged: (val) {
setSelectedRadioTile(val);
print(val);
},
title: Text(
'Male',
style: TextStyle(color: Colors.white),
),
),
RadioListTile(
value: 'Female',
activeColor: Theme.of(context).primaryColor,
groupValue: selectedRadioTile,
onChanged: (val) {
setSelectedRadioTile(val);
print(val);
},
title: Text(
'Female',
style: TextStyle(color: Colors.white),
),
),
]),
),
SizedBox(
height: 12,
),
],
),
),
),
),
),
),
if (_isLoading)
CircularProgressIndicator(
backgroundColor: Theme.of(context).primaryColor,
),
if (!_isLoading)
RaisedButton(
child: Text(
_isLogin ? 'LOGIN' : 'SIGN UP',
style: TextStyle(fontSize: 16),
),
onPressed: saveForm,
),
FlatButton(
child: Text(
'${_isLogin ? 'SIGN UP' : 'LOGIN'} INSTEAD',
style: TextStyle(color: Colors.white, fontSize: 16),
),
onPressed: () {
_switchAuthMode();
},
),
],
),
);
}
}
and this is the method which i use to switch between login and signup:
void _switchAuthMode() {
if (_isLogin) {
setState(() {
_isLogin = false;
});
} else {
setState(() {
_isLogin = true;
});
}
}
You can wrap those cardviews with animated container and change their heights using setstate and boolean.
That will result in the UI you are working to obtain, I presume.
Let me know if it helps, or you need more help.
I am making a Login Form and on error i want to change the color of my TextFormField.
Currently I am using Bloc Architecture and State management.
Here is a picture of how I want the text field on error.
Simply use text validation and test on it.
Here's a generic example :
class MyHomePageState extends State<MyHomePage> {
final _text = TextEditingController();
bool _validate = false;
#override
void dispose() {
_text.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Textfield validation'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('form cant be empty'),
TextField(
controller: _text,
decoration: InputDecoration(
filled: _validate,
fillColor: Colors.red,
labelText: 'Enter the Value',
errorText: _validate ? 'Value Can\'t Be Empty' : null,
),
),
RaisedButton(
onPressed: () {
setState(() {
_text.text.isEmpty ? _validate = true : _validate = false;
});
},
child: Text('Submit'),
textColor: Colors.white,
color: Colors.blueAccent,
)
],
),
),
);
}
}
Here's a codepen demo for it
create a method in util class and call that method as mention below
textFormField(
color: Colors.white,
hintText: "User Name",
radius: 50,
onSave: (String value) {
_loginData.email = value;
},
validator: FormValidator().validateEmail,
prefixIcon: Padding(
padding: EdgeInsets.all(0.0),
child: Icon(
Icons.person,
color: Colors.grey,
), // icon is 48px widget.
),suffixIcon: null,obscureText: false),
textFormField({
Color color,
String hintText,
double radius,
dynamic validator,
Function onSave,
dynamic prefixIcon,
dynamic suffixIcon,
bool obscureText,
}) {
return new TextFormField(
keyboardType: TextInputType.emailAddress,
autofocus: false,
obscureText: obscureText,
decoration: InputDecoration(
hintText: hintText,
errorText: "",
fillColor: color,
filled: true,
contentPadding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(radius)),
borderSide: BorderSide(color: color, width: 0)),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(radius)),
borderSide: BorderSide(color: color, width: 0)),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(radius)),
borderSide: BorderSide(color: color, width: 0)),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(radius)),
borderSide: BorderSide(color: color, width: 0)),
disabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(radius)),
borderSide: BorderSide(color: color, width: 0)),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(radius)),
borderSide: BorderSide(color: color, width: 0)),
prefixIcon: prefixIcon,
suffixIcon: suffixIcon,
),
validator: validator,
// validator: FormValidator().validateEmail,
onSaved:
onSave, /*onSaved: (String value) {
_loginData.email = value;
},*/
);
}
This example might be helpful:
TextFormField(
decoration: InputDecoration(
errorStyle: TextStyle(
color: Colors.white,
)
),
),