Flutter - Cursor keep blinking after change Form input - flutter

I have a regular form on my APP, and when i load de screen no input is focused and no input has the cursor blinking...
Although, when run throw the inputs and fill them, or not, the cursor keeps blinking as i show on the image above:
The picture only show 3, but all of them are blinking. My point is that i need to keep only the focused input with the cursor blinking.
Heres the Form Code:
class RegisterView extends StatefulWidget {
const RegisterView({Key? key}) : super(key: key);
#override
State<RegisterView> createState() => _RegisterViewState();
}
class _RegisterViewState extends State<RegisterView> {
final _formKey = GlobalKey<FormState>();
final FocusScopeNode _node = FocusScopeNode();
String name = '';
String email = '';
String nif = '';
String password = '';
String _errorMessage = '';
TextEditingController nameCtrl = TextEditingController();
TextEditingController emailCtrl = TextEditingController();
TextEditingController nifCtrl = TextEditingController();
TextEditingController passwordCtrl = TextEditingController();
#override
void dispose() {
// TODO: implement dispose
_node.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
UserProvider userProvider =
Provider.of<UserProvider>(context, listen: false);
return Scaffold(
appBar: AppBar(
leading: const CustomBackButton(),
title: const Text('Register',
style: TextStyle(
color: kPrimaryColor,
fontSize: 16.0,
fontWeight: FontWeight.bold)),
centerTitle: true,
),
body: GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
child: SingleChildScrollView(
child: Form(
key: _formKey,
child: FocusScope(
node: _node,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
children: [
const Padding(
padding: EdgeInsets.symmetric(vertical: 15.0),
child: Text(
'Please set your personal data:',
style:
TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
),
Padding(
padding: const EdgeInsets.only(bottom: 10.0),
child: Row(
children: [
Text(_errorMessage,
style: const TextStyle(color: Colors.red)),
],
),
),
TextFormField(
controller: nameCtrl,
keyboardType: TextInputType.number,
decoration: InputDecoration(
filled: true,
fillColor: Colors.grey[250],
contentPadding: const EdgeInsets.all(10.0),
hintText: 'Name',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: const BorderSide(
color: kPrimaryColor,
width: 2,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: const BorderSide(
color: kPrimaryColor,
width: 2,
),
),
),
onChanged: (String data) {
setState(() {
name = data;
});
},
onEditingComplete: _node.nextFocus,
),
const SizedBox(height: 15),
TextFormField(
controller: emailCtrl,
keyboardType: TextInputType.number,
decoration: InputDecoration(
filled: true,
fillColor: Colors.grey[250],
contentPadding: const EdgeInsets.all(10.0),
hintText: 'Email',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: const BorderSide(
color: kPrimaryColor,
width: 2,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: const BorderSide(
color: kPrimaryColor,
width: 2,
),
),
),
onChanged: (String data) {
setState(() {
email = data;
});
},
validator: (String? value) {
if (value!.isEmpty) {
return 'Required';
} else if (!emailRegex.hasMatch(value)) {
return 'Please set a valid email';
}
},
onEditingComplete: _node.nextFocus,
),
const SizedBox(height: 15),
TextFormField(
controller: nifCtrl,
keyboardType: TextInputType.number,
decoration: InputDecoration(
filled: true,
fillColor: Colors.grey[250],
contentPadding: const EdgeInsets.all(10.0),
hintText: 'NIF',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: const BorderSide(
color: kPrimaryColor,
width: 2,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: const BorderSide(
color: kPrimaryColor,
width: 2,
),
),
),
onChanged: (String data) {
setState(() {
nif = data;
});
},
onEditingComplete: _node.nextFocus,
),
const SizedBox(height: 15),
TextFormField(
controller: passwordCtrl,
keyboardType: TextInputType.number,
decoration: InputDecoration(
filled: true,
fillColor: Colors.grey[250],
contentPadding: const EdgeInsets.all(10.0),
hintText: 'Password',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: const BorderSide(
color: kPrimaryColor,
width: 2,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: const BorderSide(
color: kPrimaryColor,
width: 2,
),
),
),
onChanged: (String data) {
setState(() {
password = data;
});
},
validator: (String? value) {
if (value!.isEmpty) {
return 'Campo obrigatório';
} else if (value.length < 6) {
return 'Password deve conter pelo menos 6 caracteres';
}
},
onEditingComplete: _node.nextFocus,
),
const SizedBox(height: 15),
RoundedButton(
bgColor: kPrimaryColor,
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
userProvider.isLoading
? const SpinKitFadingCircle(
color: Colors.white,
size: 25.0,
)
: const Text(
'Save',
style: TextStyle(
fontSize: 16,
color: Colors.white,
fontWeight: FontWeight.w700,
),
),
],
),
onPressed: () {
if (_formKey.currentState!.validate()) {
print('Ok to register');
}
},
)
],
),
),
),
),
),
),
);
}
}

Related

Add textfield flutter to firebase Form

i'm trying to make a simple crud , now i'm trying to add "patient" to my db .
But i have a problem nothing register in the database ,
i initializedmy values ( i don't know if its corect im still beginner in dart ) but the only data i get in firestore is the initial values
here's my code , can you help me please ?
const kTextFieldDecoration = InputDecoration(
hintText: 'Enter a value',
hintStyle: TextStyle(color: Colors.grey),
contentPadding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(32.0)),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Color(0xff5AA7A7), width: 1.0),
borderRadius: BorderRadius.all(Radius.circular(32.0)),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Color(0xff5AA7A7), width: 2.0),
borderRadius: BorderRadius.all(Radius.circular(32.0)),
),
);
class Background extends StatefulWidget {
final Widget child;
const Background({
Key? key,
required this.child,
}) : super(key: key);
#override
_BackgroundState createState() => _BackgroundState();
}
class _BackgroundState extends State<Background>{
final _auth = FirebaseAuth.instance;
late XFile _image;
late String name;
late String birth ;
late int pass ;
late String? genre ;
TextEditingController dateinput = TextEditingController();
final List<String> genderItems = [
'Male',
'Female',
];
String? selectedValue;
final ImagePicker _picker = ImagePicker();
bool showSpinner = false;
void _showPicker(context) {
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return SafeArea(
child: Container(
child: new Wrap(
children: <Widget>[
],
),
),
);
}
);
}
#override
void initState() {
genre = "None";
birth="None";
pass=0000;
name="null";
super.initState();
}
void addPatient() {
FirebaseFirestore.instance.collection("patient").add(
{
"name" : name,
"genre" : genre,
"birth" : birth,
"pass" : pass,
}).then((value){
print("Patient data Added");
});
}
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
resizeToAvoidBottomInset: false ,
backgroundColor: Colors.white,
body: ModalProgressHUD(
inAsyncCall: showSpinner,
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
child : CircleAvatar(
radius: 70.0,
backgroundImage: AssetImage("assets/images/avatar.png"),
),
),
Container(
padding: EdgeInsets.only( left: 100.0),
child : Positioned(
bottom: 50.0,
right: 20.0,
child: InkWell(onTap: () {
_showPicker(context);
},
child: Icon(
Icons.camera_alt_outlined,
size:28.0,color:
Colors.teal,
),
), ), ), TextField(
keyboardType: TextInputType.text,
textAlign: TextAlign.center,
onChanged: (value) {
name = value;
},
decoration: kTextFieldDecoration.copyWith(
labelText: 'Name')),
TextField(
obscureText: true,
textAlign: TextAlign.center,
onChanged: (value) {
pass = value as int;
},
decoration: kTextFieldDecoration.copyWith(
labelText: 'Password',)),
Column(
children: [
DropdownButtonFormField(
decoration:
InputDecoration(
hintStyle: TextStyle(color: Colors.grey),
contentPadding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(32.0)),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Color(0xff5AA7A7), width: 1.0),
borderRadius: BorderRadius.all(Radius.circular(32.0)),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Color(0xff5AA7A7), width: 2.0),
borderRadius: BorderRadius.all(Radius.circular(32.0)),
),
labelText: 'Gender',
),
isExpanded: true,
icon: const Icon(
Icons.arrow_drop_down,
color: Colors.teal,
),
iconSize: 30,
items: genderItems
.map((item) =>
DropdownMenuItem<String>(
value: item,
child: Text(
item,
style: const TextStyle(
fontSize: 14,
),
),
))
.toList(),
validator: (value) {
if (value == null) {
return 'Please select gender.';
}
},
onChanged: (value) {
genre = value as String? ; //Do something when changing the item if you want.
},
onSaved: (value) {
selectedValue = value.toString();
},
),
],
),
TextField(
controller: dateinput,
obscureText: true,
textAlign: TextAlign.center,
onChanged: (value) {
birth = value ;
},
decoration: InputDecoration(
hintStyle: TextStyle(color: Colors.grey),
contentPadding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(32.0)),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Color(0xff5AA7A7), width: 1.0),
borderRadius: BorderRadius.all(Radius.circular(32.0)),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Color(0xff5AA7A7), width: 2.0),
borderRadius: BorderRadius.all(Radius.circular(32.0)),
),
//icon of text field
labelText: "Date of Birth" , //label text of field
),
onTap: () async {
DateTime? birth = await showDatePicker(
context: context, initialDate: DateTime.now(),
firstDate: DateTime(1900), //DateTime.now() - not to allow to choose before today.
lastDate: DateTime(2023),
);
if(birth != null ){
print(birth);
setState(() {
dateinput.text = birth as String;
});
}else{
print("Date is not selected");
}}, ),
RoundedButton(
colour: Color(0xff96D7C6),
title: 'Submit',
onPressed: () async {
setState(() {
showSpinner = true;
});
addPatient();
Navigator.pushNamed(context, 'patient_screen');
},),],),),), ), ); }}

SingleChildScrollView isn't working in my login screen

this is the login screen I had Implemented using flutter. I want this screen to be scrollable. how can I do that? I have uploaded my login screen code for your reference. I have tried out my column wrap with a single-child scroll view. but it doesn't work. there are multiple columns, maybe I'm wrapping the wrong column. I appriciate your help on this.
class LoginScreen extends StatefulWidget {
const LoginScreen({Key? key}) : super(key: key);
#override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
#override
Widget build(BuildContext context) {
final Size = MediaQuery.of(context).size;
return GestureDetector(
onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
child: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [Color.fromARGB(255, 3, 86, 124), Color(0xff141a3a)],
begin: Alignment.topRight,
end: Alignment.bottomLeft,
)),
child: Scaffold(
backgroundColor: Colors.transparent,
resizeToAvoidBottomInset: false,
body: Padding(
padding: const EdgeInsets.only(top: 40, left: 20, right: 20),
child: Column(
children: [
Expanded(
flex: 2,
child: Column(
children: [
// Spacer(flex: 1),
Image(
image: const AssetImage(
'assets/images/LogoVector.png',
),
height: Size.width / 2.9,
width: Size.width / 2.9,
),
SizedBox(height: 5),
Text(
"LOGIN",
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 30,
color: textWhite,
fontFamily: "Roboto"),
),
],
),
),
// const Spacer(flex: 1),
const Expanded(flex: 3, child: Center(child: LoginForm())),
],
),
),
),
),
);
}
}
class LoginForm extends StatefulWidget {
const LoginForm({Key? key}) : super(key: key);
#override
_LoginFormState createState() => _LoginFormState();
}
Map<String, String> loginUserData = {
'email': '',
'password': '',
'id': '',
'userName': '',
'token': '',
'userStatus': '',
};
class _LoginFormState extends State<LoginForm> {
TextEditingController emailEditingController = new TextEditingController();
TextEditingController passwordEditingController = new TextEditingController();
final _formKey = GlobalKey<FormState>();
String email = "";
String password = "";
String username = "";
bool isLoading = false;
bool typing = true;
bool _isObscure = true;
#override
Widget build(BuildContext context) {
final Size = MediaQuery.of(context).size;
return Form(
key: _formKey,
autovalidateMode: AutovalidateMode.disabled,
child: Column(
children: [
TextFormField(
controller: emailEditingController,
enabled: true,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
borderSide: const BorderSide(
color: textWhite,
),
// borderSide: BorderSide.none
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
borderSide: const BorderSide(color: textWhite),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
borderSide: const BorderSide(color: Colors.red),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
borderSide: const BorderSide(color: Colors.red),
),
isDense: true,
contentPadding: EdgeInsets.fromLTRB(10, 30, 10, 0),
hintText: "Email/ Username",
hintStyle: TextStyle(
color: textWhite, fontFamily: "Roboto", fontSize: 14),
),
style: TextStyle(color: textWhite),
validator: (String? UserName) {
if (UserName != null && UserName.isEmpty) {
return "Email can't be empty";
}
return null;
},
onChanged: (String? text) {
email = text!;
// print(email);
},
onSaved: (value) {
loginUserData['email'] = value!;
},
),
SizedBox(
height: 10,
),
TextFormField(
controller: passwordEditingController,
obscureText: _isObscure,
enabled: true,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
borderSide: const BorderSide(color: textWhite),
// borderSide: BorderSide.none
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
borderSide: const BorderSide(color: textWhite),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
borderSide: const BorderSide(color: Colors.red),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
borderSide: const BorderSide(color: Colors.red),
),
isDense: true,
contentPadding: EdgeInsets.fromLTRB(10, 10, 10, 0),
suffixIcon: IconButton(
icon: Icon(
_isObscure ? Icons.visibility : Icons.visibility_off),
color: textWhite,
onPressed: () {
setState(() {
_isObscure = !_isObscure;
});
}),
hintText: "Password",
hintStyle: TextStyle(
color: textWhite,
fontFamily: "Roboto",
fontSize: 14,
)),
style: TextStyle(color: textWhite),
validator: (String? Password) {
if (Password != null && Password.isEmpty) {
return "Password can't be empty";
}
return null;
},
onChanged: (String? text) {
password = text!;
print(password);
},
onSaved: (value) {
loginUserData['password'] = value!;
},
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
child: CheckboxListTile(
title: const Text(
"Remember Me",
style: TextStyle(
color: textWhite, fontFamily: "Roboto", fontSize: 14),
),
activeColor: buttontext,
// tileColor: buttontext,
value: checkedValue,
onChanged: (newValue) {
FocusManager.instance.primaryFocus?.unfocus();
setState(() {
if (isLoading != true) {
checkedValue = newValue!;
print(newValue);
}
});
},
contentPadding: EdgeInsets.only(left: 0, top: 0),
controlAffinity:
ListTileControlAffinity.leading, // <-- leading Checkbox
),
),
TextButton(
child: Text(
"Forget Password",
style: TextStyle(
color: textWhite, fontFamily: "Roboto", fontSize: 14),
),
onPressed: () {
Get.to(() => Forget_Screen());
},
)
],
),
SizedBox(height: 40),
isLoading
? SpinKitDualRing(
color: textWhite,
size: 40,
)
: GestureDetector(
child: MainButton("Login"),
onTap: () async {
FocusManager.instance.primaryFocus?.unfocus();
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
await LoginData();
// Get.to(BottomNavigation());
}
},
),
SizedBox(height: 15),
Container(
width: 275.0,
height: 40.0,
child: OutlinedButton(
onPressed: () {
Get.to(() => const Signup_Screen());
},
child: const Text(
'Signup',
style: TextStyle(
fontSize: 15, fontFamily: "Roboto", color: textWhite
//fontWeight: FontWeight.w500,
// color: Colors.black,
),
),
style: OutlinedButton.styleFrom(
side: const BorderSide(
width: 1.0,
color: textWhite,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
),
),
)
],
),
);
}
}
You should wrap everything under the Scaffold:
Scaffold(
backgroundColor: Colors.transparent,
resizeToAvoidBottomInset: false,
body: SingleChildScrollView(child: Padding(
padding: const EdgeInsets.only(top: 40, left: 20, right: 20),
child: Column(
........
I can not see you using the SingleChildScrollView in then code sample you have provided with.
But if you want to make the page scrollable, Wrap the child of the scaffold in the SingleChildScrollView
Scaffold(
body: SingleChildScrollView(
....

How to add a toggle for hiding and viewing password in Flutter?

I have been trying to develop an app and for its sign up, I am not sure how and where a toggle to hide/view the password can be added. Is it under obscuretext? If so, how do I add a condition for it to my code? (Used a form to create for entering sign up details.)
Code of the form where the Custom Text Field was implemented:
_signUpForm() {
return Container(
padding: EdgeInsets.symmetric(horizontal: 25, vertical: 30),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
CustomRoundedTextField(
label: 'Email',
onChange: (val) {
email = val;
},
),
CustomRoundedTextField(
label: 'Password',
isPassword: true,
onChange: (val) {
password = val;
},
),
SizedBox(height: 40),
CustomBlueRoundedButton(
child: Text(
'Register Account',
style: TextStyle(color: Colors.white),
),
onPressed: _createAccount,
),
SizedBox(height: 15,),
Container(
child: Center(
child: Text("Already have an account?"),
),
),
SizedBox(height: 5),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
InkWell(
onTap: openLoginPage,
child: Text("Login", style: TextStyle(
color: Color(0xff1A3C90),
fontWeight: FontWeight.w700
),),
)
],
)
],
),
);
}
Custom Text Field Class Code:
class CustomRoundedTextField extends StatelessWidget {
final label;
final onChange;
final isPassword;
final bottomPadding;
final textCapitalization;
final inputType;
final controller;
final iconData;
CustomRoundedTextField(
{
this.iconData,
this.controller,
this.inputType = TextInputType.text,
this.label,
this.onChange,
this.isPassword = false,
this.bottomPadding = 16,
this.textCapitalization = TextCapitalization.none});
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(bottom: 16),
child: TextField(
controller: controller,
keyboardType: inputType,
textCapitalization: textCapitalization,
obscureText: isPassword,
style:
TextStyle(fontSize: 15, color: Colors.black),
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: BorderSide(
color: Colors.black54,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: BorderSide(
color: Colors.black,
),
),
labelText: label,
labelStyle: TextStyle(
fontSize: 15,
color: Colors.black,
fontWeight: FontWeight.w600,
),
),
onChanged: onChange,
),
);
}
}
Make your CustomRoundedTextField as StatefulWidget and add suffixIcon to TextField's InputDecoration. Below your code:
class CustomRoundedTextField extends StatefulWidget {
final label;
final onChange;
final isPassword;
final bottomPadding;
final textCapitalization;
final inputType;
final controller;
final iconData;
CustomRoundedTextField(
{
this.iconData,
this.controller,
this.inputType = TextInputType.text,
this.label,
this.onChange,
this.isPassword = false,
this.bottomPadding = 16,
this.textCapitalization = TextCapitalization.none});
#override
_CustomRoundedTextFieldState createState() => _CustomRoundedTextFieldState();
}
class _CustomRoundedTextFieldState extends State<CustomRoundedTextField> {
bool _showPwd = false;
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(bottom: 16),
child: TextField(
controller: widget.controller,
keyboardType: widget.inputType,
textCapitalization: widget.textCapitalization,
obscureText: widget.isPassword && !_showPwd,
style:
TextStyle(fontSize: 15, color: Colors.black),
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: BorderSide(
color: Colors.black54,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: BorderSide(
color: Colors.black,
),
),
labelText: widget.label,
labelStyle: TextStyle(
fontSize: 15,
color: Colors.black,
fontWeight: FontWeight.w600,
),
suffixIcon: widget.isPassword ? IconButton(
icon: Icon(_showPwd ? Icons.visibility : Icons.visibility_off),
onPressed:(){
setState((){
_showPwd = !_showPwd;
});
}
) : null,
),
onChanged: widget.onChange,
),
);
}
}

The setter 'phone=' was called on null. I/flutter (32048): Receiver: null I/flutter (32048): Tried calling: phone="48787487"

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.

I/flutter ( 8686): Another exception was thrown: NoSuchMethodError: The method 'save' was called on null

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"