I have this TextFormField and i am working on implementing a LogIn/Registration screen. The problem is that when the Validator pops the error onto the screen the borders of the TextFormField change from rounded edges to square shaped. What can i do to just print out the error? I was thinking about printing everything above or below the entire form, but what about a way to do it with the Valdiator property?
Or is there a more effective way to do it?
It also seems that the ListView in which the TextFormField resides gets destroyed in the process making it very annoying to type after the validator gets printed out on the screen.
beforeValidator
afterValidator
Just the TextFormField:
TextFormField(
validator: (String str) =>
str.isEmpty ? 'Enter a username' : null,
decoration: InputDecoration(
hintText: 'theChadMaster76',
hintStyle: TextStyle(
fontStyle: FontStyle.italic,
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.green),
borderRadius: BorderRadius.circular(35.0),
),
focusedBorder: OutlineInputBorder(
//focusBorder changes or not when user first clicks on the field
borderSide: BorderSide(color: Colors.blueAccent),
borderRadius: BorderRadius.circular(35.0),
),
prefixIcon: Icon(Icons
.account_circle), //make the icon also change its color
filled: true,
fillColor: Colors.grey.shade200,
),
textAlign: TextAlign.center,
textAlignVertical: TextAlignVertical.bottom,
onChanged: (String str) {
setState(() {
userName = str;
});
},
),
Entire file:
class RegistrationScreen extends StatefulWidget {
static const String id = 'registration_screen';
#override
_RegistrationScreenState createState() => _RegistrationScreenState();
}
class _RegistrationScreenState extends State<RegistrationScreen> {
final AuthService _auth = AuthService();
final _formKey = GlobalKey<FormState>();
bool loading = false;
String error = '';
String userName = "";
String email = "";
String password = "";
#override
Widget build(BuildContext context) {
return loading ? Loading() : Scaffold(
appBar: AppBarModel(),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 30.0),
child: Center(
child: Form(
key: _formKey,
child: ListView(
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(vertical: 50.0),
child: Center(child: Text('add logo')),
),
Padding(
padding: const EdgeInsets.only(left: 20.0, bottom: 10.0),
child: Text(
'Username:',
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.w600,
//fontStyle: FontStyle.italic,
),
),
),
TextFormField(
validator: (String str) =>
str.isEmpty ? 'Enter a username' : null,
decoration: InputDecoration(
hintText: 'theChadMaster76',
hintStyle: TextStyle(
fontStyle: FontStyle.italic,
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.green),
borderRadius: BorderRadius.circular(35.0),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blueAccent),
borderRadius: BorderRadius.circular(35.0),
),
prefixIcon: Icon(Icons
.account_circle), //make the icon also change its color
filled: true,
fillColor: Colors.grey.shade200,
),
textAlign: TextAlign.center,
textAlignVertical: TextAlignVertical.bottom,
onChanged: (String str) {
setState(() {
userName = str;
});
},
),
SizedBox(height: 30.0),
Padding(
padding: const EdgeInsets.only(left: 20.0, bottom: 10.0),
child: Text(
'Email:',
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.w600,
//fontStyle: FontStyle.italic,
),
),
),
TextFormField(
keyboardType: TextInputType.emailAddress,
validator: (String str) =>
str.isEmpty ? 'Enter an email' : null,
decoration: InputDecoration(
hintText: 'bobbyBob#gmail.com',
hintStyle: TextStyle(
fontStyle: FontStyle.italic,
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.green),
borderRadius: BorderRadius.circular(35.0),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blueAccent),
borderRadius: BorderRadius.circular(35.0),
),
prefixIcon:
Icon(Icons.mail),
filled: true,
fillColor: Colors.grey.shade200,
),
textAlign: TextAlign.center,
textAlignVertical: TextAlignVertical.bottom,
onChanged: (String str) {
setState(() {
email = str;
});
},
),
SizedBox(height: 30.0),
Padding(
padding: const EdgeInsets.only(left: 20.0, bottom: 10.0),
child: Text(
'Password:',
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.w600,
//fontStyle: FontStyle.italic,
),
),
),
TextFormField(
validator: (String str) =>
str.length < 6 ? 'Enter an password 6+ char' : null,
obscureText: true,
decoration: InputDecoration(
hintText: 'secretPassword123!',
hintStyle: TextStyle(
fontStyle: FontStyle.italic,
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.green),
borderRadius: BorderRadius.circular(35.0),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blueAccent),
borderRadius: BorderRadius.circular(35.0),
),
prefixIcon: Icon(Icons.memory),
filled: true,
fillColor: Colors.grey.shade200,
),
textAlign: TextAlign.center,
textAlignVertical: TextAlignVertical.bottom,
onChanged: (String str) {
setState(() {
password = str;
});
},
),
SizedBox(
height: 50.0,
),
Center(
child: FlatButton(
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
side: BorderSide(color: Colors.green.shade400),
),
color: Colors.green.shade400,
textColor: Colors.grey.shade300,
padding:
EdgeInsets.symmetric(horizontal: 120.0, vertical: 10.0),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'SUBMIT',
style: TextStyle(
fontSize: 18.0,
letterSpacing: 4.0,
fontStyle: FontStyle.italic,
),
),
),
onPressed: () async {
if (_formKey.currentState.validate()) {
setState(() {
loading = true;
});
dynamic result = await _auth.registerWithEmailPassUser(
email, password);
if (result == null) {
setState(() {
loading = false;
error = "please supply a valid email";
});
}
}
},
),
),
],
),
),
),
),
);
}
}
you just need to override the errorBoder style as well, like the way you did for focusedBorder,enabledBorder. below is the code snippet.
errorBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.red),
borderRadius: BorderRadius.circular(35.0),
)
and your final TextFormFiled should look like
TextFormField(
validator: (String str) =>
str.isEmpty ? 'Enter a username' : null,
decoration: InputDecoration(
hintText: 'theChadMaster76',
hintStyle: TextStyle(
fontStyle: FontStyle.italic,
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.green),
borderRadius: BorderRadius.circular(35.0),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blueAccent),
borderRadius: BorderRadius.circular(35.0),
),
errorBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.red),
borderRadius: BorderRadius.circular(35.0),
),
prefixIcon: Icon(Icons
.account_circle), //make the icon also change its color
filled: true,
fillColor: Colors.grey.shade200,
),
textAlign: TextAlign.center,
textAlignVertical: TextAlignVertical.bottom,
onChanged: (String str) {
setState(() {
userName = str;
});
},
)
You have to specify the errorBorder & focusedErrorBorder as well:
errorBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.red),
borderRadius: BorderRadius.circular(35.0),
),
focusedErrorBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.red),
borderRadius: BorderRadius.circular(35.0),
),
Refer InputDecoration for all the available options.
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 to make text field in flutter like this. I want to develop a text field in flutter
You can make this TextField like this:
TextField(
decoration: InputDecoration(
filled: true,
fillColor: Colors.white,
focusColor: Colors.white,
focusedBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.white, width: 2.0),
borderRadius: BorderRadius.circular(30),
),
border: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.white, width: 2.0),
borderRadius: BorderRadius.circular(30),
),
enabledBorder: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.white, width: 2.0),
borderRadius: BorderRadius.circular(30),
),
hintText: 'Email address',
hintStyle: const TextStyle(color: Colors.grey),
),
),
Hope it works for you:
TextField(
decoration: InputDecoration(
filled: true,
fillColor: Colors.white.withOpacity(0.6),
hintText: "Email address",
hintStyle: TextStyle(
color: Colors.grey[400],
fontWeight: FontWeight.bold
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
borderSide: BorderSide.none,
),
),
);
Column(
children:[
const TextField(
decoration: InputDecoration(
fillColor: Colors.white,
filled: true,
isDense: true,
contentPadding: EdgeInsets.symmetric(vertical: 12.0, horizontal: 16.0),
// counter: Container(),
counterText: '',
hintStyle: TextStyle(
color: Colors.grey,
fontWeight: FontWeight.w700,
fontSize: 18),
hintText: 'Email Address',
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.white),
borderRadius: BorderRadius.all(
Radius.circular(12.0),
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.white),
borderRadius: BorderRadius.all(
Radius.circular(12.0),
),
),
),
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.next,
),
SizedBox(height: 20),
const TextField(
decoration: InputDecoration(
fillColor: Colors.white,
filled: true,
isDense: true,
contentPadding: EdgeInsets.symmetric(vertical: 12.0, horizontal: 16.0),
// counter: Container(),
counterText: '',
hintStyle: TextStyle(
color: Colors.grey,
fontWeight: FontWeight.w700,
fontSize: 18),
hintText: 'Password',
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.white),
borderRadius: BorderRadius.all(
Radius.circular(8.0),
),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.white),
borderRadius: BorderRadius.all(
Radius.circular(8.0),
),
),
),
keyboardType: TextInputType.visiblePassword,
obscureText: true,
textInputAction: TextInputAction.done,
),
]
)
Please use this text field code. Import and use it everywhere
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:personal_diary/app/data/SelectedTheme.dart';
import 'package:personal_diary/app/data/ThemeData.dart';
class EditText extends StatelessWidget {
// final Color textColor;
final String hint;
final int maxLine;
final int? maxLength;
final bool isObscure;
final Color? textFieldColor, hintFieldColor;
final TextInputType? keyboardType;
final ThemeDetails themeDetails = SelectedTheme.instance.getTheme();
final double marginTop, marginBottom, marginLeft, marginRight;
final TextEditingController? controller;
final bool isReadOnly;
final double? fontSize;
final double? height;
final String? Function(String? val)? validator;
EditText(
{required this.hint,
this.maxLine = 1,
this.maxLength,
this.fontSize,
this.isReadOnly = false,
this.isObscure = false,
this.keyboardType,
this.marginTop = 0.0,
this.marginBottom = 0.0,
this.height,
this.marginLeft = 0.0,
this.textFieldColor,
this.hintFieldColor,
this.validator,
this.marginRight = 0.0,
this.controller});
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.85),
borderRadius: BorderRadius.all(Radius.circular(12.sp))),
padding: EdgeInsets.only(left: 10.w),
margin: EdgeInsets.only(
top: marginTop,
bottom: marginBottom,
right: marginRight,
left: marginLeft),
child: TextFormField(
style: TextStyle(
color: Colors.black,
fontSize: fontSize ?? 14.sp,
height: height,
),
controller: controller,
maxLines: maxLine,
readOnly: isReadOnly,
maxLength: maxLength,
validator: validator,
keyboardType: keyboardType,
obscureText: isObscure,
decoration: InputDecoration(
hintText: hint, border: InputBorder.none,
counterText: '',
hintStyle: TextStyle(
color: Colors.grey, fontSize: 14.sp
),
),
),
);
}
}
This is how you can use this code :
Column(
children : [
EditText(
hint: "Enter email",
isObscure:true,
keyboardType: TextInputType.number,
hintFieldColor: Colors.grey,
marginTop: 20.h,
maxLength: 1,
controller: confirmPasswordController,
),
]
)
The following NoSuchMethodError was thrown while handling a gesture:
The method 'phone' was called on null.
Receiver: null
Tried calling: phone= "1235451"
I'm creating a page to update user registration data, and when I click on update this error appears and nothing happens. I'm learning flutter now, and there's a lot that I don't know, can someone help me?
[User dart file]: https://i.stack.imgur.com/RLimv.png
import 'package:flutter/material.dart';
import '../../generated/l10n.dart';
import '../models/user.dart';
import '../helpers/helper.dart';
import '../elements/BlockButtonWidget.dart';
import '../helpers/app_config.dart' as config;
import 'package:mvc_pattern/mvc_pattern.dart';
import '../repository/user_repository.dart' as repository;
import '../repository/user_repository.dart';
class SettingsController extends ControllerMVC {
GlobalKey<FormState> loginFormKey;
GlobalKey<ScaffoldState> scaffoldKey;
SettingsController() {
loginFormKey = new GlobalKey<FormState>();
this.scaffoldKey = new GlobalKey<ScaffoldState>();
}
void update(User user) async {
user.deviceToken = null;
repository.update(user).then((value) {
scaffoldKey?.currentState?.showSnackBar(SnackBar(
content: Text("Atualizado com Sucesso"),
));
});
}
}
class ProfileSettingsDialog extends StatefulWidget {
final User user;
final VoidCallback onChanged;
ProfileSettingsDialog({Key key,#required this.user, this.onChanged}) : super(key: key);
#override
_ProfileSettingsDialogState createState() => _ProfileSettingsDialogState();
}
class _ProfileSettingsDialogState extends State<ProfileSettingsDialog> {
GlobalKey<FormState> _profileSettingsFormKey = new GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: Helper.of(context).onWillPop,
child: Scaffold(
resizeToAvoidBottomPadding: false,
body: Stack(
alignment: AlignmentDirectional.topCenter,
children: <Widget>[
Positioned(
top: 0,
child: Container(
width: config.App(context).appWidth(100),
height: config.App(context).appHeight(29.5),
decoration: BoxDecoration(color: Theme.of(context).accentColor),
),
),
Positioned(
top: config.App(context).appHeight(29.5) - 120,
child: Container(
width: config.App(context).appWidth(84),
height: config.App(context).appHeight(29.5),
child: Text(
S.of(context).lets_start_with_register,
style: Theme.of(context).textTheme.headline2.merge(TextStyle(color: Theme.of(context).primaryColor)),
),
),
),
Positioned(
top: config.App(context).appHeight(29.5) - 50,
child: Container(
decoration: BoxDecoration(color: Theme.of(context).primaryColor, borderRadius: BorderRadius.all(Radius.circular(10)), boxShadow: [
BoxShadow(
blurRadius: 50,
color: Theme.of(context).hintColor.withOpacity(0.2),
)
]),
margin: EdgeInsets.symmetric(
horizontal: 20,
),
padding: EdgeInsets.symmetric(vertical: 50, horizontal: 27),
width: config.App(context).appWidth(88),
// height: config.App(context).appHeight(55),
child: Form(key: _ProfileSettingsFormKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextFormField(
keyboardType: TextInputType.text,
onSaved: (input) => widget.user.phone = input,
validator: (input) => input.trim().length < 3 ? S.of(context).not_a_valid_phone : null,
decoration: InputDecoration(
labelText: "Celular",
labelStyle: TextStyle(color: Theme.of(context).accentColor),
contentPadding: EdgeInsets.all(12),
hintText: S.of(context).john_doe,
hintStyle: TextStyle(color: Theme.of(context).focusColor.withOpacity(0.7)),
prefixIcon: Icon(Icons.person_outline, color: Theme.of(context).accentColor),
border: OutlineInputBorder(borderSide: BorderSide(color: Theme.of(context).focusColor.withOpacity(0.2))),
focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: Theme.of(context).focusColor.withOpacity(0.5))),
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Theme.of(context).focusColor.withOpacity(0.2))),
),
),
SizedBox(height: 30),
TextFormField(
keyboardType: TextInputType.text,
onSaved: (input) => widget.user.address = input,
validator: (input) => input.trim().length < 3 ? S.of(context).not_a_valid_address : null,
decoration: InputDecoration(
labelText: "Endereço",
labelStyle: TextStyle(color: Theme.of(context).accentColor),
contentPadding: EdgeInsets.all(12),
hintText: 'johndoe#gmail.com',
hintStyle: TextStyle(color: Theme.of(context).focusColor.withOpacity(0.7)),
prefixIcon: Icon(Icons.alternate_email, color: Theme.of(context).accentColor),
border: OutlineInputBorder(borderSide: BorderSide(color: Theme.of(context).focusColor.withOpacity(0.2))),
focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: Theme.of(context).focusColor.withOpacity(0.5))),
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Theme.of(context).focusColor.withOpacity(0.2))),
),
),
SizedBox(height: 30),
TextFormField(
keyboardType: TextInputType.text,
onSaved: (input) => widget.user.bio = input,
validator: (input) => input.trim().length < 3 ? S.of(context).not_a_valid_biography : null,
decoration: InputDecoration(
labelText: "Biografia",
labelStyle: TextStyle(color: Theme.of(context).accentColor),
contentPadding: EdgeInsets.all(12),
hintText: 'johndoe#gmail.com',
hintStyle: TextStyle(color: Theme.of(context).focusColor.withOpacity(0.7)),
prefixIcon: Icon(Icons.alternate_email, color: Theme.of(context).accentColor),
border: OutlineInputBorder(borderSide: BorderSide(color: Theme.of(context).focusColor.withOpacity(0.2))),
focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: Theme.of(context).focusColor.withOpacity(0.5))),
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Theme.of(context).focusColor.withOpacity(0.2))),
),
),
SizedBox(height: 30),
BlockButtonWidget(
text: Text(
S.of(context).register,
style: TextStyle(color: Theme.of(context).primaryColor),
),
color: Theme.of(context).accentColor,
onPressed: () {
_profileSettingsFormKey.currentState.save();
widget.onChanged();
Navigator.pop(context);
update(currentUser.value);
//setState(() {});
},
// widget.update(currentUser.value);
),
SizedBox(height: 25),
// FlatButton(
// onPressed: () {
// Navigator.of(context).pushNamed('/MobileVerification');
// },
// padding: EdgeInsets.symmetric(vertical: 14),
// color: Theme.of(context).accentColor.withOpacity(0.1),
// shape: StadiumBorder(),
// child: Text(
// 'Register with Google',
// textAlign: TextAlign.start,
// style: TextStyle(
// color: Theme.of(context).accentColor,
// ),
// ),
// ),
],
),
),
),
),
],
),
),
);
}
InputDecoration getInputDecoration({String hintText, String labelText}) {
return new InputDecoration(
hintText: hintText,
labelText: labelText,
hintStyle: Theme.of(context).textTheme.bodyText2.merge(
TextStyle(color: Theme.of(context).focusColor),
),
enabledBorder: UnderlineInputBorder(borderSide: BorderSide(color: Theme.of(context).hintColor.withOpacity(0.2))),
focusedBorder: UnderlineInputBorder(borderSide: BorderSide(color: Theme.of(context).hintColor)),
floatingLabelBehavior: FloatingLabelBehavior.auto,
labelStyle: Theme.of(context).textTheme.bodyText2.merge(
TextStyle(color: Theme.of(context).hintColor),
),
);
}
}
I cannot see the definition of your User class but it seems that the property phone is defined as final (hence, you get the error the setter method was called on null).
You need to make the property mutable (non-final such as String phone) in order to be able to change its value in the same way as in your code.
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.
The following NoSuchMethodError was thrown while handling a gesture:
The method 'save' was called on null.
Receiver: null
Tried calling: save()
I'm creating a page to update user registration data, and when I click on update this error appears and nothing happens. I'm learning flutter now, and there's a lot that I don't know, can someone help me?
import 'package:flutter/material.dart';
import '../../generated/l10n.dart';
import '../models/user.dart';
import '../helpers/helper.dart';
import '../elements/BlockButtonWidget.dart';
import '../helpers/app_config.dart' as config;
import 'package:mvc_pattern/mvc_pattern.dart';
import '../repository/user_repository.dart' as repository;
import '../repository/user_repository.dart';
class SettingsController extends ControllerMVC {
GlobalKey<FormState> loginFormKey;
GlobalKey<ScaffoldState> scaffoldKey;
SettingsController() {
loginFormKey = new GlobalKey<FormState>();
this.scaffoldKey = new GlobalKey<ScaffoldState>();
}
void update(User user) async {
user.deviceToken = null;
repository.update(user).then((value) {
scaffoldKey?.currentState?.showSnackBar(SnackBar(
content: Text("Atualizado com Sucesso"),
));
});
}
}
class ProfileSettingsDialog extends StatefulWidget {
final User user;
final VoidCallback onChanged;
ProfileSettingsDialog({Key key, this.user, this.onChanged}) : super(key: key);
#override
_ProfileSettingsDialogState createState() => _ProfileSettingsDialogState();
}
class _ProfileSettingsDialogState extends State<ProfileSettingsDialog> {
GlobalKey<FormState> _profileSettingsFormKey = new GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: Helper.of(context).onWillPop,
child: Scaffold(
resizeToAvoidBottomPadding: false,
body: Stack(
alignment: AlignmentDirectional.topCenter,
children: <Widget>[
Positioned(
top: 0,
child: Container(
width: config.App(context).appWidth(100),
height: config.App(context).appHeight(29.5),
decoration: BoxDecoration(color: Theme.of(context).accentColor),
),
),
Positioned(
top: config.App(context).appHeight(29.5) - 120,
child: Container(
width: config.App(context).appWidth(84),
height: config.App(context).appHeight(29.5),
child: Text(
S.of(context).lets_start_with_register,
style: Theme.of(context).textTheme.headline2.merge(TextStyle(color: Theme.of(context).primaryColor)),
),
),
),
Positioned(
top: config.App(context).appHeight(29.5) - 50,
child: Container(
decoration: BoxDecoration(color: Theme.of(context).primaryColor, borderRadius: BorderRadius.all(Radius.circular(10)), boxShadow: [
BoxShadow(
blurRadius: 50,
color: Theme.of(context).hintColor.withOpacity(0.2),
)
]),
margin: EdgeInsets.symmetric(
horizontal: 20,
),
padding: EdgeInsets.symmetric(vertical: 50, horizontal: 27),
width: config.App(context).appWidth(88),
// height: config.App(context).appHeight(55),
child: Form(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextFormField(
keyboardType: TextInputType.text,
onSaved: (input) => widget.user.phone = input,
validator: (input) => input.trim().length < 3 ? S.of(context).not_a_valid_phone : null,
decoration: InputDecoration(
labelText: "Celular",
labelStyle: TextStyle(color: Theme.of(context).accentColor),
contentPadding: EdgeInsets.all(12),
hintText: S.of(context).john_doe,
hintStyle: TextStyle(color: Theme.of(context).focusColor.withOpacity(0.7)),
prefixIcon: Icon(Icons.person_outline, color: Theme.of(context).accentColor),
border: OutlineInputBorder(borderSide: BorderSide(color: Theme.of(context).focusColor.withOpacity(0.2))),
focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: Theme.of(context).focusColor.withOpacity(0.5))),
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Theme.of(context).focusColor.withOpacity(0.2))),
),
),
SizedBox(height: 30),
TextFormField(
keyboardType: TextInputType.text,
onSaved: (input) => widget.user.address = input,
validator: (input) => input.trim().length < 3 ? S.of(context).not_a_valid_address : null,
decoration: InputDecoration(
labelText: "Endereço",
labelStyle: TextStyle(color: Theme.of(context).accentColor),
contentPadding: EdgeInsets.all(12),
hintText: 'johndoe#gmail.com',
hintStyle: TextStyle(color: Theme.of(context).focusColor.withOpacity(0.7)),
prefixIcon: Icon(Icons.alternate_email, color: Theme.of(context).accentColor),
border: OutlineInputBorder(borderSide: BorderSide(color: Theme.of(context).focusColor.withOpacity(0.2))),
focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: Theme.of(context).focusColor.withOpacity(0.5))),
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Theme.of(context).focusColor.withOpacity(0.2))),
),
),
SizedBox(height: 30),
TextFormField(
keyboardType: TextInputType.text,
onSaved: (input) => widget.user.bio = input,
validator: (input) => input.trim().length < 3 ? S.of(context).not_a_valid_biography : null,
decoration: InputDecoration(
labelText: "Biografia",
labelStyle: TextStyle(color: Theme.of(context).accentColor),
contentPadding: EdgeInsets.all(12),
hintText: 'johndoe#gmail.com',
hintStyle: TextStyle(color: Theme.of(context).focusColor.withOpacity(0.7)),
prefixIcon: Icon(Icons.alternate_email, color: Theme.of(context).accentColor),
border: OutlineInputBorder(borderSide: BorderSide(color: Theme.of(context).focusColor.withOpacity(0.2))),
focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: Theme.of(context).focusColor.withOpacity(0.5))),
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: Theme.of(context).focusColor.withOpacity(0.2))),
),
),
SizedBox(height: 30),
BlockButtonWidget(
text: Text(
S.of(context).register,
style: TextStyle(color: Theme.of(context).primaryColor),
),
color: Theme.of(context).accentColor,
onPressed: () {
_profileSettingsFormKey.currentState.save();
widget.onChanged();
Navigator.pop(context);
update(currentUser.value);
//setState(() {});
},
// widget.update(currentUser.value);
),
SizedBox(height: 25),
// FlatButton(
// onPressed: () {
// Navigator.of(context).pushNamed('/MobileVerification');
// },
// padding: EdgeInsets.symmetric(vertical: 14),
// color: Theme.of(context).accentColor.withOpacity(0.1),
// shape: StadiumBorder(),
// child: Text(
// 'Register with Google',
// textAlign: TextAlign.start,
// style: TextStyle(
// color: Theme.of(context).accentColor,
// ),
// ),
// ),
],
),
),
),
),
],
),
),
);
}
InputDecoration getInputDecoration({String hintText, String labelText}) {
return new InputDecoration(
hintText: hintText,
labelText: labelText,
hintStyle: Theme.of(context).textTheme.bodyText2.merge(
TextStyle(color: Theme.of(context).focusColor),
),
enabledBorder: UnderlineInputBorder(borderSide: BorderSide(color: Theme.of(context).hintColor.withOpacity(0.2))),
focusedBorder: UnderlineInputBorder(borderSide: BorderSide(color: Theme.of(context).hintColor)),
floatingLabelBehavior: FloatingLabelBehavior.auto,
labelStyle: Theme.of(context).textTheme.bodyText2.merge(
TextStyle(color: Theme.of(context).hintColor),
),
);
}
}
You should bind the key _profileSettingsFormKey to Form, else the key would not get any state and so the currentState would be null
thus calling save() on null throws the exception
Form(
key: _profileSettingsFormKey,
child: ...
)
_profileSettingsFormKey is null, you need to use a Form widget and bind the key to it:
return Form(
key: _profileSettingsFormKey,
You forgot to assign the key to your Form, so the currentState of the key is null.
Form(
key: _profileSettingsFormKey,
// ...
)
thank you, now this error is showing
The setter 'address=' was called on null.
Receiver: null
Tried calling: address="siahduiasudi, 189"