Fluttter Scaffold ' invalid credentials' message is not showing on login - flutter

I have an app with a login page that requires and email and a password. It should bring a scaffold message at the bottom of the screen in the event that the login is not successful that is, when the code is not 200. Currently, when the login button is pressed with wrong credentials, the loading circle persists and nothing changes. This is what the error page looks like:
This is the code with the scaffold function:
void _showScaffold(String message) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(message, style: const TextStyle(color: Colors.white)),
action: SnackBarAction(
textColor: Colors.white,
label: 'Try Again',
onPressed: () {
Navigator.of(context).pushReplacementNamed('login');
},
),
backgroundColor: Colors.redAccent));
}
This is the login function where it is implemented:
_login() async {
var data = {
'email': emailController.text,
'password': passwordController.text,
};
var res = await Network().authData(data, 'auth/login');
if (res.statusCode == 200) {
var body = json.decode(res.body);
var tdata = body['data'];
var access = tdata['accessToken'];
var user = tdata['user'];
SharedPreferences localStorage = await SharedPreferences.getInstance();
localStorage.setString('token', json.encode(access));
localStorage.setString('user', json.encode(user));
return Navigator.of(context).pushReplacementNamed('dashboard');
} else {
return setState(() {
_showScaffold('Invalid Credentials');
});
}
}
And this is the code for the on pressed section of the login button:
if (_isLoading)
SizedBox(
width: 250,
height: 50,
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(
const Color.fromRGBO(46, 88, 0, 1),
)),
onPressed: () async {
setState(() {
_isLoading = false;
});
await _login();
if (!mounted) return;
setState(() {
_isLoading = true;
});
},
child: const Text(
'Login',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
))
else
const Center(
child: CircularProgressIndicator(
backgroundColor: Color.fromRGBO(46, 88, 0, 1))),
This is the code for the whole login_widget.dart file:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:mne/Network/api.dart';
import 'package:shared_preferences/shared_preferences.dart';
class LoginWidget extends StatefulWidget {
const LoginWidget({Key key}) : super(key: key);
#override
_LoginWidgetState createState() => _LoginWidgetState();
}
class _LoginWidgetState extends State<LoginWidget> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
void _showScaffold(String message) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(message, style: const TextStyle(color: Colors.white)),
action: SnackBarAction(
textColor: Colors.white,
label: 'Try Again',
onPressed: () {
Navigator.of(context).pushReplacementNamed('login');
},
),
backgroundColor: Colors.redAccent));
}
// #override
// void initState() {
// super.initState();
// _showScaffold('Invalid Credentials');
// }
TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
final _controller = TextEditingController();
_login() async {
var data = {
'email': emailController.text,
'password': passwordController.text,
};
var res = await Network().authData(data, 'auth/login');
if (res.statusCode == 200) {
var body = json.decode(res.body);
var tdata = body['data'];
var access = tdata['accessToken'];
var user = tdata['user'];
SharedPreferences localStorage = await SharedPreferences.getInstance();
localStorage.setString('token', json.encode(access));
localStorage.setString('user', json.encode(user));
return Navigator.of(context).pushReplacementNamed('dashboard');
} else {
return setState(() {
_showScaffold('Invalid Credentials');
});
}
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
bool _isObscure = true;
bool _validate = false;
bool _isLoading = true;
#override
Widget build(BuildContext context) {
// ignore: avoid_unnecessary_containers
return GestureDetector(
onTap: () {
() => FocusManager.instance.primaryFocus?.unfocus();
},
child: Container(
key: _scaffoldKey,
child: Column(
children: [
Container(
margin: const EdgeInsets.only(left: 10),
alignment: Alignment.centerLeft,
child: const Text('Email',
style: TextStyle(fontWeight: FontWeight.bold)),
),
Container(
padding: const EdgeInsets.fromLTRB(10, 10, 10, 0),
child: SizedBox(
height: 60.0,
width: 375,
child: TextFormField(
controller: emailController,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (value) {
if (value.isEmpty) {
return 'Field cannot be empty';
}
return null;
},
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
errorText:
_validate ? 'Field cannot be empty' : null,
border: const OutlineInputBorder(),
labelText: 'Email Address',
),
))),
Container(
padding: const EdgeInsets.only(top: 10),
margin: const EdgeInsets.only(left: 10),
alignment: Alignment.centerLeft,
child: const Text('Password',
style: TextStyle(fontWeight: FontWeight.bold)),
),
Container(
margin: const EdgeInsets.fromLTRB(10, 10, 10, 0),
padding: const EdgeInsets.only(bottom: 15),
child: SizedBox(
height: 60.0,
width: 375,
child: TextFormField(
controller: passwordController,
obscureText: _isObscure,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (value) {
if (value.isEmpty) {
return 'Field cannot be empty';
}
return null;
},
keyboardType: TextInputType.text,
decoration: InputDecoration(
suffixIcon: IconButton(
icon: Icon(_isObscure
? Icons.visibility
: Icons.visibility_off),
onPressed: () {
FocusScope.of(context).unfocus();
setState(() {
_isObscure = !_isObscure;
});
}),
errorText:
_validate ? 'Field cannot be empty' : null,
border: const OutlineInputBorder(),
labelText: 'Password',
),
))),
Container(
alignment: Alignment.centerLeft,
padding:
const EdgeInsets.only(left: 10, top: 15, bottom: 15),
child: TextButton(
child: const Text(
'Forgot password?',
style: TextStyle(
color: Color.fromRGBO(75, 116, 9, 1),
fontWeight: FontWeight.bold,
fontSize: 16),
),
onPressed: () {
Navigator.of(context).pushNamed('reset');
},
)),
if (_isLoading)
SizedBox(
width: 250,
height: 50,
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(
const Color.fromRGBO(46, 88, 0, 1),
)),
onPressed: () async {
setState(() {
_isLoading = false;
});
await _login();
if (!mounted) return;
setState(() {
_isLoading = true;
});
},
child: const Text(
'Login',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
))
else
const Center(
child: CircularProgressIndicator(
backgroundColor: Color.fromRGBO(46, 88, 0, 1))),
],
)));
}
}
I would like to know how to make the scaffold message show up and redirect the user back to the login page. Any help is much appreciated.

Related

Why does my code give an error of a Null Check Operator used on a null value

Here is the code
I wanted to register a user and I used a FormKey and I got the error Null
check operator use don a null value
here is what the run terminal shows
E/flutter (30851): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: Null check operator used on a null value
E/flutter (30851): #0 _RegisterScreenState.signUp (package:em_home/screens/signing/register_screen.dart:58:29)
class RegisterScreen extends StatefulWidget {
const RegisterScreen({Key? key}) : super(key: key);
#override
_RegisterScreenState createState() => _RegisterScreenState();
}
class _RegisterScreenState extends State<RegisterScreen> {
showSnackBar(String content, BuildContext context) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(content)));
}
bool _isLoading = false;
final formKey = GlobalKey<FormState>();
String email = "";
String password = "";
String fullName = "";
String dob = "";
String gender = "";
AuthMethods authMethods = AuthMethods();
Uint8List? image;
pickImage(ImageSource source) async {
final ImagePicker imagePicker = ImagePicker();
XFile? _file = await imagePicker.pickImage(source: source);
if (_file != null) {
return await _file.readAsBytes();
}
print("No Image selected");
}
void selectImage() async {
Uint8List im = await pickImage(ImageSource.gallery);
setState(() {
image = im;
});
}
signUp() async {
if (formKey.currentState!.validate()) {
setState(() {
_isLoading = true;
});
await authMethods.registerUser(email: email, password: password, name: fullName, gender: gender, dateOfBirth: dob,)
.then((value) async {
if (value == true) {
await HelperFunctions.saveUserLoggedInStatus(true);
await HelperFunctions.saveUserEmailSF(email);
await HelperFunctions.saveUserNameSF(fullName);
Navigator.pushReplacement(context, SlideLeftRoute(widget: const LoginScreen()));
} else {
showSnackBar(value, context);
setState(() {
_isLoading = false;
});
}
});
}
return null;
}
void navigatetoSignIn() {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => const LoginScreen()));
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: backgroundColor,
body: SingleChildScrollView(
child: Container(
color: backgroundColor,
padding: const EdgeInsets.symmetric(horizontal: 15),
width: double.infinity,
child: Column(
children: [
const SizedBox(
height: 30,
),
Container(
alignment: Alignment.topLeft,
child: IconButton(
onPressed: () {
Navigator.pushReplacement(
context, SlideLeftRoute(widget: const LoginScreen()));
},
icon: const Icon(
Icons.arrow_back,
size: 40,
),
),
),
const SizedBox(
height: 20,
),
Image.asset(
'assets/logos.png',
),
const Text(
"Create your account",
style: TextStyle(color: textColor, fontWeight: FontWeight.bold),
),
const SizedBox(
height: 30,
),
Stack(
children: [
// to check if Image is not equal to null
image != null
? CircleAvatar(
radius: 64,
backgroundImage: MemoryImage(image!),
)
: const CircleAvatar(
radius: 64,
backgroundImage: AssetImage(
"assets/default_profile.jpg",
),
),
Positioned(
child: IconButton(
onPressed: selectImage,
icon: const Icon(Icons.add_a_photo),
),
left: 80,
bottom: -10,
)
],
),
const SizedBox(
height: 30,
),
TextFormField(
decoration: textInputDecoration.copyWith(
labelText: "Email",
prefixIcon: Icon(
Icons.email,
)),
onChanged: (val) {
setState(() {
email = val;
});
},
// check tha validation
validator: (val) {
return RegExp(
r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+#[a-zA-Z0-9]+\.[a-zA-Z]+")
.hasMatch(val!)
? null
: "Please enter a valid email";
},
),
const SizedBox(
height: 20,
),
TextFormField(
obscureText: true,
decoration: textInputDecoration.copyWith(
labelText: "Password",
prefixIcon: Icon(
Icons.lock,
color: backgroundColor,
)),
validator: (val) {
if (val!.length < 6) {
return "Password must be at least 6 characters";
} else {
return null;
}
},
onChanged: (val) {
setState(() {
password = val;
});
},
),
const SizedBox(
height: 20,
),
TextFormField(
decoration: textInputDecoration.copyWith(
labelText: "Full Name",
prefixIcon: Icon(
Icons.person,
)),
onChanged: (val) {
setState(() {
fullName = val;
});
},
validator: (val) {
if (val!.isNotEmpty) {
return null;
} else {
return "Name cannot be empty";
}
},
),
const SizedBox(
height: 20,
),
TextFormField(
decoration: textInputDecoration.copyWith(
labelText: "Date Of Birth DD/MM/YYYY",
prefixIcon: Icon(
Icons.lock,
)),
validator: (val) {},
onChanged: (val) {
setState(() {
dob = val;
});
},
),
const SizedBox(
height: 20,
),
TextFormField(
decoration: textInputDecoration.copyWith(
labelText: "Gender",
prefixIcon: Icon(
Icons.lock,
)),
validator: (val) {},
onChanged: (val) {
setState(() {
gender = val;
});
},
),
const SizedBox(
height: 20,
),
InkWell(
onTap: signUp,
child: Container(
width: double.infinity,
alignment: AlignmentDirectional.center,
padding: const EdgeInsets.symmetric(vertical: 12),
decoration: const ShapeDecoration(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(4)),
),
color: buttonColor,
),
child: _isLoading
? const Center(
child: CircularProgressIndicator(
color: iconButtonColor,
),
)
: const Text(
"Sign up",
style: TextStyle(
color: buttonTextColor,
fontWeight: FontWeight.bold),
),
),
),
const SizedBox(
height: 50,
),
Container(
color: backgroundColor,
child: const Text("- or sign in using -"),
),
const SizedBox(
height: 25,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
GestureDetector(
onTap: () {
Navigator.push(context, CustomRoute(widget: const Scaffold(body: Center(child: Text("Coming Soon"),))));
},
child: Container(
width: 50,
height: 45,
color: Colors.white,
child: Image.asset('assets/google.png'),
),
),
const SizedBox(
width: 30,
),
GestureDetector(
onTap: () {
Navigator.push(context, CustomRoute(widget: const Scaffold(body: Center(child: Text("Coming Soon"),))));
},
child: Container(
width: 50,
height: 45,
color: Colors.white,
child: Image.asset('assets/facebook.png'),
),
),
],
),
],
),
),
),
);
}
}
please what do I do here is the snippet to the code
Wrap your UI with the FormFields inside a Form widget and pass the GlobalKey to it.
Quick guide from Flutter docs: https://docs.flutter.dev/cookbook/forms/validation

Flutter/dart: setState() called after dispose() error

I am running into a 'setState() called after dispose()' error.
I understand that this is caused because I am trying to update a component that is not present anymore.
So the issue is occuring when I click the button 'Login', which calls the funtion "_submitFormOnLogin"
Below is the code snip where I think the problem might be
void _submitFormOnLogin() async {
final isValid = _loginFormKey.currentState!.validate();
if (isValid) {
setState(() {
_isLoading = true;
});
try {
await _auth.signInWithEmailAndPassword(
email: _emailTextController.text.trim().toLowerCase(),
password: _passTextController.text.trim());
Navigator.canPop(context) ? Navigator.pop(context) : null;
} catch (error) {
setState(() {
_isLoading = false;
});
GlobalMethod.showErrorDialog(error: error.toString(), ctx: context);
print('error occurred! $error');
}
}
setState(() {
_isLoading = false;
});
}
Below is all the code for that page::
import 'package:cached_network_image/cached_network_image.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:ijob_clone_app/ForgetPassword/forget_password_screen.dart';
import 'package:ijob_clone_app/SingUpPage/signup_screen.dart';
import '../Services/global_methods.dart';
import '../Services/global_variables.dart';
class Login extends StatefulWidget {
#override
State<Login> createState() => _LoginState();
}
class _LoginState extends State<Login> with TickerProviderStateMixin {
late Animation<double> _animation;
late AnimationController _animationController;
final TextEditingController _emailTextController =
TextEditingController(text: '');
final TextEditingController _passTextController =
TextEditingController(text: '');
final FocusNode _passFocusNode = FocusNode();
bool _isLoading = false;
bool _obscureText = true;
final FirebaseAuth _auth = FirebaseAuth.instance;
final _loginFormKey = GlobalKey<FormState>();
#override
void dispose() {
_animationController.dispose();
_emailTextController.dispose();
_passTextController.dispose();
_passFocusNode.dispose();
super.dispose();
}
#override
void initState() {
_animationController =
AnimationController(vsync: this, duration: const Duration(seconds: 20));
_animation =
CurvedAnimation(parent: _animationController, curve: Curves.linear)
..addListener(() {
setState(() {});
})
..addStatusListener((animationStatus) {
if (animationStatus == AnimationStatus.completed) {
_animationController.reset();
_animationController.forward();
}
});
_animationController.forward();
super.initState();
}
void _submitFormOnLogin() async {
final isValid = _loginFormKey.currentState!.validate();
if (isValid) {
setState(() {
_isLoading = true;
});
try {
await _auth.signInWithEmailAndPassword(
email: _emailTextController.text.trim().toLowerCase(),
password: _passTextController.text.trim());
Navigator.canPop(context) ? Navigator.pop(context) : null;
} catch (error) {
setState(() {
_isLoading = false;
});
GlobalMethod.showErrorDialog(error: error.toString(), ctx: context);
print('error occurred! $error');
}
}
setState(() {
_isLoading = false;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(children: [
CachedNetworkImage(
imageUrl: loginUrlImage,
placeholder: (context, url) => Image.asset(
'assets/images/wallpaper.jpg',
fit: BoxFit.fill,
),
errorWidget: (context, url, error) => const Icon(Icons.error),
width: double.infinity,
height: double.infinity,
fit: BoxFit.cover,
alignment: FractionalOffset(_animation.value, 0),
),
Container(
color: Colors.black54,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 80),
child: ListView(
children: [
Padding(
padding: const EdgeInsets.only(left: 80, right: 80),
child: Image.asset('assets/images/login.png')),
const SizedBox(
height: 15,
),
Form(
key: _loginFormKey,
child: Column(children: [
TextFormField(
textInputAction: TextInputAction.next,
onEditingComplete: () => FocusScope.of(context)
.requestFocus(_passFocusNode),
keyboardType: TextInputType.emailAddress,
controller: _emailTextController,
validator: (value) {
if (value!.isEmpty || !value.contains('#')) {
return 'Please enter a valid Email address';
} else {
return null;
}
},
style: const TextStyle(color: Colors.white),
decoration: const InputDecoration(
hintText: 'Email',
hintStyle: TextStyle(color: Colors.white),
enabledBorder: UnderlineInputBorder(
borderSide:
BorderSide(color: Colors.white)),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
errorBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.red),
))),
const SizedBox(
height: 5,
),
TextFormField(
textInputAction: TextInputAction.next,
focusNode: _passFocusNode,
keyboardType: TextInputType.visiblePassword,
controller: _passTextController,
obscureText: !_obscureText,
validator: (value) {
if (value!.isEmpty || value.length < 7) {
return 'please enter a valid password';
} else {
return null;
}
},
style: const TextStyle(color: Colors.white),
decoration: InputDecoration(
suffixIcon: GestureDetector(
onTap: () {
setState(() {
_obscureText = !_obscureText;
});
},
child: Icon(
_obscureText
? Icons.visibility
: Icons.visibility_off,
color: Colors.white,
)),
hintText: 'Password',
hintStyle: const TextStyle(color: Colors.white),
enabledBorder: const UnderlineInputBorder(
borderSide:
BorderSide(color: Colors.white)),
focusedBorder: const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
),
errorBorder: const UnderlineInputBorder(
borderSide: BorderSide(color: Colors.red),
),
),
),
])),
const SizedBox(height: 15),
Align(
alignment: Alignment.bottomRight,
child: TextButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ForgetPassword()));
},
child: const Text('Forget password?',
style: TextStyle(
color: Colors.white,
fontSize: 17,
fontStyle: FontStyle.italic,
)))),
const SizedBox(
height: 10,
),
MaterialButton(
onPressed: _submitFormOnLogin,
color: Colors.cyan,
elevation: 8,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(13)),
child: Padding(
padding: EdgeInsets.symmetric(vertical: 14),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text('Login',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 16,
))
],
),
),
),
const SizedBox(height:40),
Center(
child:RichText(
text:TextSpan(
children:[
const TextSpan(
text:'Do not have an account?',
style:TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
const TextSpan(text: ' '),
TextSpan(
recognizer: TapGestureRecognizer()
..onTap = () => Navigator.push(context, MaterialPageRoute(builder: (context) => SignUp() )),
text: 'SignUp',
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 20,
)
)
]
)
)
)
],
)))
]));
}
}
A widget can be deleted during an asynchronous operation. This case is called an async gap. Read more about it here.
You need to check the mounted state before setState:
if (mounted) {
setState(() {
// do smith
}
}
or
if (mounted) {
Navigator.canPop(context) ? Navigator.pop(context) : null;
}

How to make a simple admin page in flutter with a given email and password in flutter?

How can I add an admin page to the existing pages?
I just want one default admin to enter which will only display users from Firebase. I would like a specific email and password to be given which will allow access for that one admin.
I'm attaching the login page
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'startuppage.dart';
class MyLogin extends StatefulWidget {
const MyLogin({Key? key}) : super(key: key);
#override
State<MyLogin> createState() => _MyLoginState();
}
class _MyLoginState extends State<MyLogin> {
//editing controller
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
int _success = 1 ;
late String _userEmail = "";
final user = FirebaseAuth.instance.currentUser;
Future SignIn() async {
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: emailController.text.trim(),
password: passwordController.text.trim()
);
}
#override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(
//color: Color(0xFFaac8ba),
gradient: LinearGradient
(begin: Alignment.bottomLeft,
end: Alignment.bottomRight,
colors: [
Color(0xFFde6262),
Color(0xFFffb88c)
]
),
),
child : Scaffold(
backgroundColor: Colors.transparent, //By default, in scaffold the bg color is white.
body: Container(
padding: const EdgeInsets.only(top: 130, left: 35, right: 0),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Welcome Back\nTo Check-it.",
style: TextStyle(
color: Colors.black,
fontSize: 30,
fontFamily: 'Montserrat',
letterSpacing: 3,
fontWeight: FontWeight.bold,
),
),
const SizedBox(
height: 50.0,
),
TextField(
controller: emailController,
keyboardType: TextInputType.emailAddress,
decoration: const InputDecoration(
hintText: "Email",
prefixIcon: Icon(Icons.mail, color: Colors.black,)
),
),
const SizedBox(
height: 20.0,
),
TextField(
controller:passwordController,
obscureText: true,
keyboardType: TextInputType.visiblePassword,
decoration: const InputDecoration(
hintText: "Password",
prefixIcon: Icon(Icons.lock, color: Colors.black,)
),
),
const SizedBox(
height: 50.0,
),
ElevatedButton(
onPressed: () async{
// _signIn();
SignIn();
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const Imageslider()),
);
},
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(Colors.black12),
),
child: const Text("Login",
style: TextStyle(
fontSize: 18,
color: Colors.black54),
),
),
const SizedBox(
height: 10.0,
),
Container(
alignment: Alignment.bottomCenter,
child: Text(
_success == 1
?''
: (
_success == 2
? 'Sign-in successful! '
: 'Sign-in failed!'),
style: const TextStyle(
color: Colors.white70,
)
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
onPressed: () {
Navigator.pushNamed(context,'signup');
},
child: const Text ('New User? Sign Up',
style : TextStyle(
decoration: TextDecoration.underline,
fontSize: 18,
color: Colors.black45,
),
)),
],
),
],
),
),
),
),
);
}
}
Sign Up Page Code :
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'login.dart';
import 'startuppage.dart';
final FirebaseAuth _auth = FirebaseAuth.instance;
class Mysignup extends StatefulWidget {
const Mysignup({Key? key}) : super(key: key);
#override
State<Mysignup> createState() => _MysignupState();
}
class _MysignupState extends State<Mysignup> {
Future<FirebaseApp> _initializeFirebase() async {
FirebaseApp firebaseApp = await Firebase.initializeApp();
return firebaseApp;
}
//editing controller
final TextEditingController name = TextEditingController();
final TextEditingController emailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
late bool _success;
bool isLoading = false;
Future<User?> _register(String name, String email, String password) async{
FirebaseAuth _auth = FirebaseAuth.instance;
FirebaseFirestore _firestore = FirebaseFirestore.instance;
try {
UserCredential userCrendetial = await _auth.createUserWithEmailAndPassword(email: emailController.text, password: passwordController.text);
print("Account created Succesfull");
userCrendetial.user?.updateDisplayName(name);
await _firestore.collection('users').doc(_auth.currentUser?.uid).set({
"name": name,
"email": email,
"uid": _auth.currentUser?.uid,
});
return userCrendetial.user;
} catch (e) {
print(e);
return null;
}
}
#override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(
gradient: LinearGradient
(colors: [
Color(0xFF02aab0),
Color(0xFF00cdac)
],
),
),
child : Scaffold(
backgroundColor: Colors.transparent, //By default, in scaffold the bg color is white.
body: Container(
padding: const EdgeInsets.only(top: 150, left: 35, right: 35),
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Let's Create Together.",
style: TextStyle(
color: Colors.black,
fontSize: 30,
letterSpacing: 3,
fontWeight: FontWeight.bold,
),
),
const SizedBox(
height: 40.0,
),
TextField(
controller:name,
keyboardType: TextInputType.name,
decoration: const InputDecoration(
hintText: "Name",
prefixIcon: Icon(Icons.account_circle_rounded, color: Colors.black,)
),
),
const SizedBox(
height: 20.0,
),
TextField(
controller:emailController,
keyboardType: TextInputType.emailAddress,
decoration: const InputDecoration(
hintText: "Email",
prefixIcon: Icon(Icons.mail, color: Colors.black,)
),
),
const SizedBox(
height: 20.0,
),
TextField(
controller:passwordController,
obscureText: true,
keyboardType: TextInputType.visiblePassword,
decoration: const InputDecoration(
hintText: "Password",
prefixIcon: Icon(Icons.lock, color: Colors.black,)
),
),
const SizedBox(
height: 80.0,
),
ElevatedButton(
onPressed: () async{
if (name.text.isNotEmpty &&
emailController.text.isNotEmpty &&
passwordController.text.isNotEmpty) {
setState(() {
isLoading = true;
});
_register(name.text, emailController.text, passwordController.text).then((user) {
if (user == null) {
setState(() {
isLoading = false;
});
Navigator.push(
context, MaterialPageRoute(builder: (_) => MyLogin()));
print("Account Created Sucessful");
} else {
print("Login Failed");
setState(() {
isLoading = false;
});
}
});
} else {
print("Please enter all the fields");
}
},
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(Colors.black12),
),
child: const Text("Sign Up",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.black54),
),
),
],
),
),
),
),
);
}
}
I'm a beginner in FLutter. Please help. Thanks in advance!
You'll want to use StreamBuilder to respond to the FirebaseAuth.instance.authStateChanges() stream that is shown in the first snippet on getting the current user, then detect whether it is the admin user who signed in based on their UID, and then show them the admin page of your UI.
Something like:
child: StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, userSnapshot) {
if (userSnapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
}
if (userSnapshot.connectionState == ConnectionState.done) {
if (!userSnapshot.hasData) {
// TODO: return screen where they sign in
}
else if (userSnapshot.data!.uid == "uidOfYourAdminUser") {
// TODO: return admin screen
}else{
// TODO: return screen for regular signed in user
}
}
}
)

When routing to another page I get "There are multiple heroes that share the same tag within a subtree"

I am trying to navigate from one screen to another with route. When I hit the button for the page to move to the route provided I get the error:
I/flutter ( 8790): Another exception was thrown: There are multiple heroes that share the same tag within a subtree.
Sharing with you the source code:
import 'dart:convert';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_counter/flutter_counter.dart';
import 'package:gender_selection/gender_selection.dart';
import 'package:group_chats/addContactUI.dart';
import 'package:group_chats/addPhone.dart';
import 'package:group_chats/letGoUI.dart';
import 'package:http/http.dart' as http;
import 'package:image_picker/image_picker.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'Animation/FadeAnimation.dart';
import 'Model/insertUserModel.dart';
class AddProfileUI extends StatefulWidget {
final List<String> listFriends;
final String phone;
AddProfileUI(this.listFriends, this.phone);
#override
_AddProfileUIState createState() => _AddProfileUIState();
}
class _AddProfileUIState extends State<AddProfileUI> {
File _image;
final picker = ImagePicker();
final _formKey = GlobalKey<FormState>();
String name = "";
String city = "";
TextEditingController dobController = TextEditingController();
bool single = false;
Gender gender;
final _scaffoldKey = GlobalKey<ScaffoldState>();
int defaultValue = 18;
List<String> selectedContact;
SharedPreferences prefs;
bool _loading = true;
Future initPrefs() async {
prefs = await SharedPreferences.getInstance();
}
uploadImage(String userId) async {
try {
FormData formData = new FormData.fromMap({
"file":
await MultipartFile.fromFile(_image.path, filename: "$userId.jpg"),
});
var response = await Dio().post(
"https://us-central1-app-backend-fc090.cloudfunctions.net/webApi/api/v1/upload_profile/$userId",
data: formData);
if (response.statusCode == 200)
return response.data;
else
return null;
} catch (e) {
print(e.toString());
return null;
}
}
Future<InsertUserModel> insertData() async {
try {
for (int i = 0; i < selectedContact.length; i++) {
if (selectedContact[i][0] == "0") {
selectedContact[i] = selectedContact[i].replaceRange(0, 1, "+972");
}
}
var body = jsonEncode({
"gender": gender.index == 0 ? "male" : "female",
"city": city,
"last_login": {},
"friends": selectedContact ?? [],
"single": single,
"name": name,
"phone_number": widget.phone,
"age": defaultValue
});
final String apiUrl =
"https://us-central1-app-backend-fc090.cloudfunctions.net/webApi/api/v1/users/${AddPhoneUI.uid}";
final response = await http.post(apiUrl,
headers: {"content-type": "application/json"}, body: body);
if (response.statusCode == 200) {
final responseString = response.body;
return insertUserModelFromJson(responseString);
}
} catch (e) {
setState(() {
_loading = false;
});
}
}
getUserData() async {
try {
final String apiUrl =
"https://us-central1-app-backend-fc090.cloudfunctions.net/webApi/api/v1/users/";
final response = await http.get(apiUrl);
if (response.statusCode == 200) {
final responseString = response.body;
return insertUserModelFromJson(responseString);
}
} catch (e) {
setState(() {
_loading = false;
});
Scaffold.of(context).showSnackBar(SnackBar(
backgroundColor: Colors.red,
content: Text('Error: ${e.toString()}'),
duration: Duration(milliseconds: 2500),
));
}
}
Future<void> _selectStartingDate(BuildContext context) async {
DateTime selectedDate = DateTime.now();
final DateTime picked = await showDatePicker(
context: context,
initialDate: selectedDate,
firstDate: DateTime(1950),
lastDate: DateTime(
DateTime.now().year, DateTime.now().month, DateTime.now().day),
);
if (picked != null && picked != selectedDate)
setState(() {
selectedDate = picked;
dobController.text = selectedDate.year.toString() +
"-" +
selectedDate.month.toString() +
"-" +
selectedDate.day.toString();
});
}
Future getImage() async {
final pickedFile = await picker.getImage(source: ImageSource.gallery);
setState(() {
_image = File(pickedFile.path);
});
}
showPopUp(BuildContext context) {
showDialog(
context: context,
builder: (context) => AlertDialog(
shape:
OutlineInputBorder(borderRadius: BorderRadius.circular(14.0)),
content: Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
height: 20.0,
),
Text(
"My Profile",
style: TextStyle(
fontSize: 27.0, fontWeight: FontWeight.w600),
),
SizedBox(
height: 30.0,
),
RichText(
text: TextSpan(
text: "Your friends will be able to\nsee ",
style: TextStyle(
color: Colors.black,
fontSize: 18.0,
),
children: <TextSpan>[
TextSpan(
text: 'only',
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.w500)),
TextSpan(text: 'your picture and\name.'),
],
)),
SizedBox(
height: 10.0,
),
RichText(
text: TextSpan(
text: "Other fields are used for\n",
style: TextStyle(
color: Colors.black,
fontSize: 18.0,
),
children: <TextSpan>[
TextSpan(
text: 'research issues',
style: TextStyle(
color: Colors.blue,
fontWeight: FontWeight.w500)),
TextSpan(text: "only."),
],
)),
SizedBox(
height: 10.0,
),
RichText(
text: TextSpan(
text: "Please fill all the fields.",
style: TextStyle(
color: Colors.black,
fontSize: 18.0,
),
)),
SizedBox(
height: 80.0,
),
MaterialButton(
shape: OutlineInputBorder(
borderSide: BorderSide(width: 1.0)),
color: Colors.white38,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 20.0),
child: Text(
"Ok, got it",
style: TextStyle(fontSize: 18.0),
),
),
onPressed: () {
Navigator.pop(context);
},
),
],
),
),
));
}
#override
void initState() {
super.initState();
selectedContact = widget.listFriends;
initPrefs();
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
body: SafeArea(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(right: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {},
),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddContactUI(),
)).then((value) {
setState(() {
selectedContact = value;
});
});
},
child: Column(
children: [
Icon(
Icons.supervisor_account,
size: 40.0,
),
Text("Add Friends"),
],
),
)
],
),
),
Container(
child: GestureDetector(
onTap: () async {
await getImage();
},
child: CircleAvatar(
radius: 60.0,
backgroundImage: _image != null
? Image.file(_image).image
: Image.asset("assets/empty.png").image,
backgroundColor: Colors.transparent,
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: FadeAnimation(
1.7,
Form(
key: _formKey,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Color(0xff5E17EB).withOpacity(0.3),
blurRadius: 20,
offset: Offset(0, 10),
)
]),
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
border: Border(
bottom:
BorderSide(color: Colors.grey[200]))),
child: TextFormField(
textInputAction: TextInputAction.next,
onFieldSubmitted: (_) =>
FocusScope.of(context).nextFocus(),
onChanged: (val) {
setState(() {
name = val;
});
},
validator: (val) =>
val.isEmpty ? "Enter Name" : null,
decoration: InputDecoration(
border: InputBorder.none,
hintText: "Name",
hintStyle: TextStyle(color: Colors.grey)),
),
),
Container(
decoration: BoxDecoration(
border: Border(
bottom:
BorderSide(color: Colors.grey[200]))),
padding: EdgeInsets.all(10),
child: TextFormField(
textInputAction: TextInputAction.next,
keyboardType: TextInputType.text,
onChanged: (val) {
setState(() {
city = val;
});
},
validator: (val) {
if (val.isEmpty) return "Enter City";
// if (val.length < 6)
// return "Password should be at least 6 characters";
return null;
},
decoration: InputDecoration(
border: InputBorder.none,
hintText: "City",
hintStyle: TextStyle(color: Colors.grey)),
),
),
Container(
height: 140.0,
padding: EdgeInsets.all(10),
child: GenderSelection(
selectedGender: gender,
maleText: "", //default Male
femaleText: "", //default Female
linearGradient: LinearGradient(colors: [
Colors.indigo,
Colors.black
]), //List: [Colors.indigo, Colors.black]
selectedGenderIconBackgroundColor:
Colors.indigo, // default red
checkIconAlignment:
Alignment.centerRight, // default bottomRight
selectedGenderCheckIcon:
null, // default Icons.check
onChanged: (Gender gender) {
this.gender = gender;
print(this.gender);
},
equallyAligned: true,
animationDuration: Duration(milliseconds: 400),
isCircular: true, // default : true,
isSelectedGenderIconCircular: true,
opacityOfGradient: 0.6,
padding: const EdgeInsets.all(3),
size: 120, //default : 120
),
),
SizedBox(
height: 10.0,
),
Row(
children: [
Checkbox(
value: single,
onChanged: (value) {
setState(() {
single = !single;
});
},
),
Text(
"Are you Single?",
style: TextStyle(fontSize: 16.0),
)
],
),
Padding(
padding: const EdgeInsets.all(14.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
"Age:",
style: TextStyle(fontSize: 18.0),
),
Counter(
initialValue: defaultValue,
buttonSize: 35.0,
textStyle: TextStyle(fontSize: 25.0),
minValue: 0,
color: Colors.black,
maxValue: 80,
step: 1,
decimalPlaces: 0,
onChanged: (value) {
// get the latest value from here
setState(() {
defaultValue = value;
});
},
),
],
),
),
],
),
),
),
),
),
SizedBox(
height: 20.0,
),
FadeAnimation(
1.9,
MaterialButton(
shape: OutlineInputBorder(borderSide: BorderSide(width: 1.0)),
color: Colors.black,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 10.0, horizontal: 20.0),
child: Text(
"Next",
style: TextStyle(
fontSize: 18.0,
color: Colors.white,
),
),
),
onPressed: () async {
if (_formKey.currentState.validate()) {
InsertUserModel result = await insertData();
// var imageResult = await uploadImage(result.id);
print(result.data[0].id);
if (_image != null) {
await uploadImage(result.data[0].id);
}
setState(() {
_loading = false;
});
if (result != null) {
await prefs.setString("userID", result.data[0].id);
final snackBar = SnackBar(
content: Text(
result.message,
style: TextStyle(color: Colors.white),
),
backgroundColor: Colors.green,
duration: Duration(milliseconds: 2000),
);
_scaffoldKey.currentState.showSnackBar(snackBar);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => LetGoUI(result.data[0].id),
));
} else {
final snackBar = SnackBar(
content: Text(
"Here is some error, please try again later!",
style: TextStyle(color: Colors.white),
),
backgroundColor: Colors.red,
duration: Duration(milliseconds: 2000),
);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
}
},
),
)
],
),
),
),
);
}
}
I really don't understand what is the problem because I'm not using any Heros and not have double FloatingActionButton.
How do I solve this?
Thanks
There might be problem with showing snackbar while navigating. you should remove that problem by calling following method before navigating.
void removeSnackBarCallsBeforeNavigation() {
ScaffoldMessenger.of(context).removeCurrentSnackBar();
}

Bottom Navigation bar disappears on sign in, but returns when I go to another page and back?

I am trying to create an app that will show the user a generic homepage with products and give them the option to navigate to an account page where, if they are not signed in they will be shown a sign in/sign up page or if they have signed in, they will be shown their profile.
I have managed to get the sign in/sign out part working, but when I sign in and navigate to the profile page, my bottom navigation bar disappears. However, when I navigate to another page and back, it reappears.
Here is my home.dart file which controls navigation for my app:
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
PageController _pageController = PageController();
List<Widget> _screens = [HomePage(), InboxPage(), AccountController()];
int _selectedIndex = 0;
void _onPageChanged(int index) {
setState(() {
_selectedIndex = index;
});
}
void _onItemTapped(int selectedIndex) {
_pageController.jumpToPage(selectedIndex);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
controller: _pageController,
children: _screens,
onPageChanged: _onPageChanged,
physics: NeverScrollableScrollPhysics(),
),
bottomNavigationBar: BottomNavigationBar(onTap: _onItemTapped, items: [
BottomNavigationBarItem(
icon: Icon(
Icons.home,
color: _selectedIndex == 0 ? Colors.blueAccent : Colors.grey,
),
title: Text(
'Home',
style: TextStyle(
color: _selectedIndex == 0 ? Colors.blueAccent : Colors.grey,
),
),
),
BottomNavigationBarItem(
icon: Icon(
Icons.email,
color: _selectedIndex == 1 ? Colors.blueAccent : Colors.grey,
),
title: Text(
'Inbox',
style: TextStyle(
color: _selectedIndex == 1 ? Colors.blueAccent : Colors.grey,
),
),
),
BottomNavigationBarItem(
icon: Icon(
Icons.account_circle,
color: _selectedIndex == 2 ? Colors.blueAccent : Colors.grey,
),
title: Text(
'Account',
style: TextStyle(
color: _selectedIndex == 2 ? Colors.blueAccent : Colors.grey,
),
),
),
]),
);
}
}
My accountcontroller.dart code which helps determine whether a user is logged in or not:
class AccountController extends StatelessWidget {
#override
Widget build(BuildContext context) {
final AuthService auth = Provider.of(context).auth;
return StreamBuilder(
stream: auth.onAuthStateChanged,
builder: (context, AsyncSnapshot<String> snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
final bool signedIn = snapshot.hasData;
return signedIn ? ProfileView() : SignUpPage();
}
return CircularProgressIndicator();
});
}
}
My profileview.dart:
class ProfileView extends StatefulWidget {
#override
_ProfileViewState createState() => _ProfileViewState();
}
class _ProfileViewState extends State<ProfileView> {
#override
Widget build(BuildContext context) {
return
Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(80),
child: MainAppBar(
text: 'Account',
)),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Text('Account Page'),
showSignOut(context),
goToHomepage(context),
],
),
),
);
}
}
Widget showSignOut(context) {
return RaisedButton(
child: Text('Sign Out'),
onPressed: () async {
try {
await Provider.of(context).auth.signOut();
Navigator.pushNamed(context, '/homepage');
print('Signed Out');
} catch (e) {
print(e);
}
});
}
Widget goToHomepage(context) {
return RaisedButton(
child: Text('Go to homepage'),
onPressed: () async {
try {
Navigator.pushNamed(context, '/homepage');
} catch (e) {
print(e);
}
});
}
And finally my signup.dart file which contains my sign up/sign in code:
enum AuthFormType { signIn, signUp }
class SignUpPage extends StatefulWidget {
final AuthFormType authFormType;
SignUpPage({Key key, this.authFormType}) : super(key: key);
#override
_SignUpPageState createState() =>
_SignUpPageState(authFormType: this.authFormType);
}
class _SignUpPageState extends State<SignUpPage> {
AuthFormType authFormType;
_SignUpPageState({this.authFormType});
final formKey = GlobalKey<FormState>();
String _firstName,
_lastName,
_email,
_confirmEmail,
_password,
_confirmPassword,
_dateOfBirth;
bool validate() {
final form = formKey.currentState;
form.save();
if (form.validate()) {
form.save();
print('true');
return true;
} else {
print('false');
return false;
}
}
void switchFormState(String state) {
formKey.currentState.reset();
if (state == 'signIn') {
setState(() {
authFormType = AuthFormType.signIn;
});
} else {
setState(() {
authFormType = AuthFormType.signUp;
});
}
}
void submit() async {
final CollectionReference userCollection =
Firestore.instance.collection('UserData');
if (validate()) {
try {
final auth = Provider.of(context).auth;
if (authFormType == AuthFormType.signIn) {
String uid = await auth.signInWithEmailAndPassword(_email, _password);
print("Signed In with ID $uid");
Navigator.of(context).pushReplacementNamed('/home');
} else {
String uid = await auth.createUserWithEmailAndPassword(
_email,
_password,
);
userCollection.document(uid).setData({
'First Name': _firstName,
'Last Name': _lastName,
'Date of Birth': _dateOfBirth
});
print("Signed up with New ID $uid");
Navigator.of(context).pushReplacementNamed('/home');
}
} catch (e) {
print(e);
}
}
}
DateTime selectedDate = DateTime.now();
TextEditingController _date = new TextEditingController();
Future<Null> _selectDate(BuildContext context) async {
DateFormat formatter =
DateFormat('dd/MM/yyyy'); //specifies day/month/year format
final DateTime picked = await showDatePicker(
context: context,
initialDate: selectedDate,
firstDate: DateTime(1901, 1),
builder: (BuildContext context, Widget child) {
return Theme(
data: ThemeData.light().copyWith(
colorScheme: ColorScheme.light(
primary: kPrimaryColor,
onPrimary: Colors.black,),
buttonTheme: ButtonThemeData(
colorScheme: Theme.of(context)
.colorScheme
.copyWith(primary: Colors.black),
),
),
child: child,
);
},
lastDate: DateTime(2100));
if (picked != null && picked != selectedDate)
setState(() {
selectedDate = picked;
_date.value = TextEditingValue(
text: formatter.format(
picked)); //Use formatter to format selected date and assign to text field
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(80),
child: MainAppBar(
text: buildAppBarText(),
)),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Center(
child: Container(
child: Column(
children: <Widget>[
Align(
child: Text(buildTitleText(), style: AppBarTextStyle),
),
Container(
padding: EdgeInsets.only(top: 10),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Form(
key: formKey,
child: Column(
children: buildInputs() + buildSwitchText(),
)),
),
],
),
),
),
),
));
}
buildHeaderText() {
String _headerText;
if (authFormType == AuthFormType.signUp) {
_headerText = "Don't have an account?";
} else {
_headerText = "Already have an account?";
}
return _headerText;
}
List<Widget> buildInputs() {
List<Widget> textFields = [];
DateFormat dateFormat = DateFormat("yyyy-MM-dd HH:mm:ss");
if (authFormType == AuthFormType.signIn) {
textFields.add(TextFormField(
style: TextStyle(
fontSize: 12.0,
),
decoration: buildSignUpInputDecoration('Email'),
validator: SignInEmailValidator.validate,
onSaved: (value) => _email = value.trim()));
textFields.add(SizedBox(
height: 15,
));
textFields.add(
TextFormField(
style: TextStyle(
fontSize: 12.0,
),
decoration: buildSignUpInputDecoration('Password'),
obscureText: true,
validator: SignInPasswordValidator.validate,
onSaved: (value) => _password = value.trim(),
),
);
} else {
textFields.clear();
//if we're in the sign up state, add name
// add email & password
textFields.add(TextFormField(
style: TextStyle(
fontSize: 12.0,
),
decoration: buildSignUpInputDecoration('First Name'),
validator: NameValidator.validate,
onSaved: (value) => _firstName = value,
));
textFields.add(SizedBox(
height: 15,
));
textFields.add(TextFormField(
style: TextStyle(
fontSize: 12.0,
),
decoration: buildSignUpInputDecoration('Last Name'),
onSaved: (value) => _lastName = value,
validator: NameValidator.validate,
));
textFields.add(SizedBox(
height: 15,
));
textFields.add(TextFormField(
style: TextStyle(
fontSize: 12.0,
),
decoration: buildSignUpInputDecoration('Email Address'),
onSaved: (value) => _email = value.trim(),
validator: SignInEmailValidator.validate,
));
textFields.add(SizedBox(
height: 15,
));
textFields.add(TextFormField(
style: TextStyle(
fontSize: 12.0,
),
decoration: buildSignUpInputDecoration('Confirm Email Address'),
onSaved: (value) => _confirmEmail = value,
validator: (confirmation) {
return confirmation == _email
? null
: "Confirm Email Address should match email address";
},
));
textFields.add(SizedBox(
height: 15,
));
textFields.add(TextFormField(
style: TextStyle(
fontSize: 12.0,
),
decoration: buildSignUpInputDecoration('Password'),
obscureText: true,
onSaved: (value) => _password = value,
));
textFields.add(SizedBox(
height: 15,
));
textFields.add(TextFormField(
style: TextStyle(
fontSize: 12.0,
),
decoration: buildSignUpInputDecoration('Confirm Password'),
onSaved: (value) => _confirmPassword = value,
validator: (confirmation) {
return confirmation == _password
? null
: "Confirm Password should match password";
}));
textFields.add(SizedBox(
height: 15,
));
textFields.add(GestureDetector(
onTap: () => _selectDate(context),
child: AbsorbPointer(
child: TextFormField(
style: TextStyle(fontSize: 12.0),
controller: _date,
keyboardType: TextInputType.datetime,
decoration: InputDecoration(
isDense: true,
fillColor: Colors.white,
hintText: 'Date of Birth',
filled: true,
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(width: 0.0),
),
contentPadding:
const EdgeInsets.only(left: 14.0, bottom: 10.0, top: 10.0),
),
onSaved: (value) => _dateOfBirth = value,
),
),
));
textFields.add(SizedBox(
height: 15,
));
}
return textFields;
}
List<Widget> buildSwitchText() {
String _switchButtonTextPart1, _switchButtonTextPart2, _newFormState;
if (authFormType == AuthFormType.signIn) {
_switchButtonTextPart1 = "Haven't got an account? ";
_switchButtonTextPart2 = 'Sign Up';
_newFormState = 'signUp';
} else {
_switchButtonTextPart1 = 'Already have an account? ';
_switchButtonTextPart2 = 'Sign In';
_newFormState = 'signIn';
}
return [
SizedBox(height: 5.0),
Container(
width: MediaQuery.of(context).size.height * 0.7,
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
),
color: kPrimaryColor,
textColor: Colors.black,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
buildTitleText(),
style: TextStyle(fontFamily: FontNameDefault, fontSize: 15.0),
),
),
onPressed: submit),
),
SizedBox(
height: 5.0,
),
RichText(
text: TextSpan(
style: TextStyle(
fontFamily: FontNameDefault,
color: Colors.black,
fontSize: 12.0,
),
children: <TextSpan>[
TextSpan(text: _switchButtonTextPart1),
TextSpan(
text: _switchButtonTextPart2,
style: TextStyle(
decoration: TextDecoration.underline,
color: Colors.black,
fontSize: 12.0),
recognizer: TapGestureRecognizer()
..onTap = () {
switchFormState(_newFormState);
})
]),
),
];
}
String buildAppBarText() {
String _switchAppBarHeader;
if (authFormType == AuthFormType.signIn) {
_switchAppBarHeader = "Already have an account?";
} else {
_switchAppBarHeader = "Don't have an account?";
}
return _switchAppBarHeader;
}
String buildTitleText() {
String _switchTextHeader;
if (authFormType == AuthFormType.signIn) {
_switchTextHeader = "Sign In";
} else {
_switchTextHeader = "Sign Up";
}
return _switchTextHeader;
}
}
InputDecoration buildSignUpInputDecoration(String hint) {
return InputDecoration(
isDense: true,
fillColor: Colors.white,
hintText: hint,
filled: true,
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(width: 0.0),
),
contentPadding: const EdgeInsets.only(left: 14.0, bottom: 10.0, top: 10.0),
);
}
Any ideas?
The HomePage(), InboxPage() and AccountController() are in your home-widget, which contains the bottomNavigationBar.
Your profile and signup pages are different pages with its own scaffold.
You have to create one central "index" widget wich holds every sub-page and the navigationbar.