Related
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 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
}
}
}
)
Hi in the below code when I enter my mobile number, password and then click on the login button nothing is happening. My API working in Postman is not working here.
When I press the button it is not working, Entering a valid mobile number and password are not working.
Can anyone help me to find where I did any mistakes?
Login_screen.dart:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:sample_live/home_screen.dart';
import 'package:sample_live/model/login_model.dart';
import 'package:sample_live/splash_screen.dart';
import 'package:sample_live/login_otp.dart';
import 'ProgressHUD.dart';
import 'api/api_service.dart';
class LoginScreen extends StatefulWidget {
String name;
LoginScreen({this.name});
#override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final mobileController = TextEditingController();
final passwordController = TextEditingController();
LoginRequestModel requestModel;
bool isApiCallProcess = false;
GlobalKey<FormState> globalFormKey = GlobalKey<FormState>();
LoginRequestModel loginRequestModel;
final scaffoldKey = GlobalKey<ScaffoldState>();
#override
void initState(){
super.initState();
requestModel=new LoginRequestModel();
}
#override
Widget build(BuildContext context) {
return ProgressHUD(
child: _uiSetup(context),
inAsyncCall: isApiCallProcess,
opacity: 0.3,
);
}
Widget _uiSetup(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Login", style: TextStyle(color: Colors.white)),
centerTitle: true,
),
body:
Stack(
children: [
Padding(
padding: EdgeInsets.all(30),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('assets/images/hand.png',),
Padding(
padding: EdgeInsets.all(10),
child: Text("Welcome Doctor! ",
style: TextStyle(
color: Colors.black,
fontSize: 20,
fontWeight: FontWeight.bold
),),
),
Padding(
padding: EdgeInsets.all(10),
),
Text("Let's treat everyone great",
style: TextStyle(
color: Colors.black,
fontSize: 15,
),),
Padding(
padding: EdgeInsets.all(10),
),
TextFormField(
minLines: 1,
keyboardType: TextInputType.number,
onSaved: (input) => loginRequestModel.Mobile = input,
textInputAction: TextInputAction.next,
decoration: InputDecoration(
labelText: "Enter Mobile No.",
hintText: "Enter Mobile No.",
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(16.0)))),
),
SizedBox(
height: 10,
),
TextFormField(
onSaved: (input) =>
loginRequestModel.Password = input,
validator: (input) =>
input.length < 3
? "Password should be more than 3 characters"
: null,
minLines: 1,
obscureText: true,
keyboardType: TextInputType.text,
textInputAction: TextInputAction.next,
decoration: InputDecoration(
labelText: "Password",
hintText: "Password",
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(16.0)))),
),
SizedBox(
height: 10,
),
Container(
width: double.infinity,
padding: EdgeInsets.symmetric(vertical: 20, horizontal: 20),
margin: EdgeInsets.symmetric(vertical: 20, horizontal: 20),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30)
),
child: RaisedButton(
color: Color(0xFF0769AA),
onPressed: () {
if (validateAndSave()) {
print(loginRequestModel.toJson());
setState(() {
isApiCallProcess = true;
});
APIService apiService = new APIService();
apiService.login(loginRequestModel).then((value) {
if (value != null) {
setState(() {
isApiCallProcess = false;
});
if (value.Status.isNotEmpty) {
final snackBar = SnackBar(
content: Text("Login Successful"));
scaffoldKey.currentState
.showSnackBar(snackBar);
} else {
final snackBar =
SnackBar(content: Text(value.Message));
scaffoldKey.currentState
// ignore: deprecated_member_use
.showSnackBar(snackBar);
}
}
});
}
},
child: Text(
"Login",
style: TextStyle(color: Colors.white),
),
),
),
SizedBox(
height: 10,
),
Text("Or",
style: TextStyle(
color: Colors.black,
fontSize: 15,
),),
Container(
width: double.infinity,
child: FlatButton(
color: Color(0xFF0769AA),
onPressed: () {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => LoginOtp("Welcome")),
(route) => false);
},
child: Text(
"Login With OTP",
style: TextStyle(color: Colors.white),
),
),
),
SizedBox(
height: 10,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
GestureDetector(
onTap: () {
// write your function
Navigator.push(
context,
MaterialPageRoute(
builder: (contex) => SplashScreen()));
},
child: Text(
"Forgot Password",
style: TextStyle(
color: Colors.blue,
fontSize: 16,
fontWeight: FontWeight.bold,
)
)),
],
),
],
),
),
Container(
alignment: Alignment.bottomCenter,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
"By logging in or signing up, you agree to the",
textAlign: TextAlign.end,
style: TextStyle(
color: Colors.black,
fontSize: 12,
),
),
Text(
"Privacy Policy & Terms and Condition",
textAlign: TextAlign.end,
style: TextStyle(
color: Colors.blue,
fontSize: 12,
),
),
],
)
)
]),
);
}
bool validateAndSave() {
final form = globalFormKey.currentState;
if (form.validate()) {
form.save();
return true;
}
return false;
}
}
In the welcome screen, I have two button which is login and register. For the first time, when i try to login to the login screen, it did not navigate to the Home Page. For the second try, I want to login again, it can't back to the login page (stuck at Welcome Screen). Can anyone help me? Thank you
Welcome Screen Code:
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
class WelcomeScreen extends StatefulWidget {
#override
_WelcomeScreenState createState() => _WelcomeScreenState();
}
class _WelcomeScreenState extends State<WelcomeScreen> {
final FirebaseAuth _auth = FirebaseAuth.instance;
navigateToLogin() async {
Navigator.pushReplacementNamed(context, "Login");
}
navigateToRegister() async {
Navigator.pushReplacementNamed(context, "SignUp");
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Column(
children: <Widget>[
SizedBox(height: 35.0),
Container(
height: 400,
child: Image(
image: AssetImage("assets/girlsave.png"),
fit: BoxFit.contain,
),
),
SizedBox(height: 20),
RichText(
text: TextSpan(
text: 'Welcome to ',
style: TextStyle(
fontSize: 25.0,
fontWeight: FontWeight.bold,
color: Colors.orange),
children: <TextSpan>[
TextSpan(
text: 'MONGER!',
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.bold,
color: Colors.orange))
])),
SizedBox(height: 10.0),
Text(
'Your Personal Money Tracker',
style: TextStyle(color: Colors.black),
),
SizedBox(height: 30.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
padding: EdgeInsets.only(left: 30, right: 30),
onPressed: navigateToLogin,
child: Text(
'LOGIN',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
color: Colors.orange),
SizedBox(width: 20.0),
RaisedButton(
padding: EdgeInsets.only(left: 30, right: 30),
onPressed: navigateToRegister,
child: Text(
'REGISTER',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
color: Colors.orange),
],
),
SizedBox(height: 20.0),
],
),
),
);
}
}
Login Page Code:
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:monger_app/WelcomeScreen/signup.dart';
class LoginPage extends StatefulWidget {
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final FirebaseAuth _auth = FirebaseAuth.instance;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
String _email, _password;
checkAuthentification() async {
_auth.authStateChanges().listen((user) {
if (user != null) {
print(user);
Navigator.pushReplacementNamed(context, "/");
}
});
}
#override
void initState() {
super.initState();
this.checkAuthentification();
}
login() async {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
try {
await _auth.signInWithEmailAndPassword(
email: _email, password: _password);
} catch (e) {
showError(e.message);
print(e);
}
}
}
showError(String errormessage) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('ERROR'),
content: Text(errormessage),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('OK'))
],
);
});
}
navigateToSignUp() async {
Navigator.push(context, MaterialPageRoute(builder: (context) => SignUpPage()));
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Colors.white,
appBar: AppBar(
elevation: 0,
brightness: Brightness.light,
backgroundColor: Colors.white,
leading: IconButton(
onPressed: (){
Navigator.pop(context);
},
icon: Icon(Icons.arrow_back_ios,
size: 20,
color: Colors.black,),
),
),
body: SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
Container(
height: 400,
child: Image(
image: AssetImage("assets/girlsave.png"),
fit: BoxFit.contain,
),
),
Container(
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
Container(
child: TextFormField(
validator: (input) {
if (input.isEmpty) return 'Enter Email';
},
decoration: InputDecoration(
labelText: 'Email',
prefixIcon: Icon(Icons.email)),
onSaved: (input) => _email = input),
),
Container(
child: TextFormField(
validator: (input) {
if (input.length < 6)
return 'Provide Minimum 6 Character';
},
decoration: InputDecoration(
labelText: 'Password',
prefixIcon: Icon(Icons.lock),
),
obscureText: true,
onSaved: (input) => _password = input),
),
SizedBox(height: 20),
RaisedButton(
padding: EdgeInsets.fromLTRB(70, 10, 70, 10),
onPressed: login,
child: Text('LOGIN',
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.bold)),
color: Colors.orange,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
)
],
),
),
),
GestureDetector(
child: Text('Create an Account?'),
onTap: navigateToSignUp,
)
],
),
),
));
}
}
Sign Up code:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class SignUpPage extends StatefulWidget {
#override
_SignUpPageState createState() => _SignUpPageState();
}
class _SignUpPageState extends State<SignUpPage> {
FirebaseAuth _auth = FirebaseAuth.instance;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
String _username, _email, _password;
checkAuthentication() async {
_auth.authStateChanges().listen((user) async {
if (user != null) {
Navigator.pushReplacementNamed(context, "/");
}
});
}
#override
void initState() {
super.initState();
this.checkAuthentication();
}
signUp() async {
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
try {
UserCredential user = await _auth.createUserWithEmailAndPassword(
email: _email, password: _password);
if (user != null) {
// UserUpdateInfo updateuser = UserUpdateInfo();
// updateuser.displayName = _name;
// user.updateProfile(updateuser);
await _auth.currentUser.updateProfile(displayName: _username);
// await Navigator.pushReplacementNamed(context,"/") ;
}
} catch (e) {
showError(e.message);
print(e);
}
}
}
showError(String errormessage) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('ERROR'),
content: Text(errormessage),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('OK'))
],
);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Colors.white,
appBar: AppBar(
elevation: 0,
brightness: Brightness.light,
backgroundColor: Colors.white,
leading: IconButton(
onPressed: (){
Navigator.pop(context);
},
icon: Icon(Icons.arrow_back_ios,
size: 20,
color: Colors.black,),
),
),
body: SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
Container(
height: 400,
child: Image(
image: AssetImage("assets/girlsave.png"),
fit: BoxFit.contain,
),
),
Container(
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
Container(
child: TextFormField(
validator: (input) {
if (input.isEmpty) return 'Enter Username';
},
decoration: InputDecoration(
labelText: 'Username',
prefixIcon: Icon(Icons.person),
),
onSaved: (input) => _username = input),
),
Container(
child: TextFormField(
validator: (input) {
if (input.isEmpty) return 'Enter Email';
},
decoration: InputDecoration(
labelText: 'Email',
prefixIcon: Icon(Icons.email)),
onSaved: (input) => _email = input),
),
Container(
child: TextFormField(
validator: (input) {
if (input.length < 6)
return 'Provide Minimum 6 Character';
},
decoration: InputDecoration(
labelText: 'Password',
prefixIcon: Icon(Icons.lock),
),
obscureText: true,
onSaved: (input) => _password = input),
),
SizedBox(height: 20),
RaisedButton(
padding: EdgeInsets.fromLTRB(70, 10, 70, 10),
onPressed: signUp,
child: Text('SignUp',
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.bold)),
color: Colors.orange,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
)
],
),
),
),
],
),
),
));
}
}
Main Code:
import 'package:flutter/material.dart';
import 'package:monger_app/WelcomeScreen/login.dart';
import 'package:monger_app/WelcomeScreen/signup.dart';
import 'package:monger_app/WelcomeScreen/welcome_screen.dart';
import 'package:monger_app/page/root.dart';
import 'package:monger_app/theme/colors.dart';
import 'package:firebase_core/firebase_core.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primaryColor: primary
),
debugShowCheckedModeBanner: false,
home:
WelcomeScreen(),
routes: <String,WidgetBuilder>{
"Login" : (BuildContext context)=>LoginPage(),
"SignUp":(BuildContext context)=>SignUpPage(),
"start":(BuildContext context)=>Root(),
},
);
}
}
HomePage Code
import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart';
import 'package:monger_app/page/setting.dart';
import 'package:monger_app/theme/colors.dart';
import 'package:animated_bottom_navigation_bar/animated_bottom_navigation_bar.dart';
import 'package:monger_app/page/transaction.dart';
import 'package:monger_app/page/statistics.dart';
import 'package:monger_app/page/account.dart';
import 'package:monger_app/page/record.dart';
import 'package:firebase_auth/firebase_auth.dart';
class Root extends StatefulWidget {
#override
_RootState createState() => _RootState();
}
class _RootState extends State<Root> {
final FirebaseAuth _auth = FirebaseAuth.instance;
User user;
bool isloggedin = false;
checkAuthentification() async {
_auth.authStateChanges().listen((user) {
if (user == null) {
Navigator.of(context).pushReplacementNamed("start");
}
});
}
int pageIndex = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: getBody(),
bottomNavigationBar: getFooter(),
floatingActionButton: FloatingActionButton(
onPressed: (){
setTabs(4);
},
child: Icon(Icons.add, size: 25),
backgroundColor: primary,
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
);
}
Widget getBody(){
return IndexedStack(
index: pageIndex,
children: [
Transaction(),
Statistics(),
Account(),
Settings(),
Record()
],
);
}
Widget getFooter(){
List<IconData> iconItems = [
Ionicons.md_bookmarks,
Ionicons.md_stats,
Ionicons.md_wallet,
Ionicons.ios_settings,
];
return AnimatedBottomNavigationBar(
activeColor: primary,
splashColor: secondary,
inactiveColor: Colors.black.withOpacity(0.5),
icons: iconItems,
activeIndex: pageIndex,
gapLocation: GapLocation.center,
notchSmoothness: NotchSmoothness.softEdge,
leftCornerRadius: 10,
iconSize: 25,
rightCornerRadius: 10,
onTap: (index) {
setTabs(index);
});
}
setTabs(index) {
setState(() {
pageIndex = index;
});
}
}
You have this code:
Navigator.pushReplacementNamed(context, "/");
but you do not have the named route "/" registered.
From your code, your Home Page is registered as "start".
So you should update the name of the route to "start" and that should work.
Your updated code should be as below:
Navigator.pushReplacementNamed(context, "start");
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.