So i'm building an app that has a login (i'm knew to flutter so i'm just getting code on youtube and try to add it) and it's supposed to have a bottom bar that leeds to de home page and the profile screen. In the profile screen he can log out.
The problem is, the app was all good, but I tried to add the bottom bar, (i had to add a AuthWrapper()
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:pap_test/tabs_screen.dart';
import 'login_signup/screens/login_screen.dart';
class AuthWrapper extends StatelessWidget {
const AuthWrapper({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final FirebaseAuth _auth = FirebaseAuth.instance;
return StreamBuilder(
stream: _auth.authStateChanges(),
builder: (context, user) {
User? _user = user.data as User?;
if (_user != null) {
return const TabsScreen();
} else {
return const LoginScreen();
}
},
);
}
}
That takes to the home page and the profile page.
// ignore_for_file: prefer_const_constructors, prefer_const_literals_to_create_immutables
import 'package:flutter/material.dart';
import 'disciplinas/disciplinas_screen.dart';
import 'login_signup/screens/home_screen.dart';
class TabsScreen extends StatefulWidget {
const TabsScreen({Key? key}) : super(key: key);
@override
_TabsScreenState createState() => _TabsScreenState();
}
class _TabsScreenState extends State<TabsScreen> {
final List<Widget> _pages = [
DisciplinasScreen(),
HomeScreen(),
];
int _selectedPageIndex = 0;
void _selectPage(int index) {
setState(() {
_selectedPageIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'',
), //seja qual for a opção do bottom bar selecionada ele irá dar o titulo que indicamos e mesmo para a outra página
),
body: _pages[_selectedPageIndex],
bottomNavigationBar: BottomNavigationBar(
onTap: _selectPage,
backgroundColor: Colors.black,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.account_circle_outlined),
label: 'Profile',
),
],
),
);
}
}
the problem is that when i'm in the app, when i rebuild it, the bottom bar is there, but the app bar gets all weird, and when i go to the profile screen, log out and then sign in the app bar gets back to normal but the bottom bar isn't there.
the rotes in the main
routes: {
'/': (ctx) => AuthWrapper(),
DisciplinaModuloScreen.routeName: (ctx) => DisciplinaModuloScreen(),
DownloadScreen.routeName: (ctx) => DownloadScreen(),
UploadResumoScreen.routeName: (ctx) => UploadResumoScreen(),
},
the log in
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import '../../disciplinas/disciplinas_screen.dart';
import '../screens/registration_screen.dart';
class LoginScreen extends StatefulWidget {
const LoginScreen({Key? key}) : super(key: key);
@override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
//form key
final _formKey = GlobalKey<FormState>();
//editing controller
final TextEditingController emailController = new TextEditingController();
final TextEditingController passwordController = new TextEditingController();
// firebase
final _auth = FirebaseAuth.instance;
// string for displaying the error Message
String? errorMessage;
@override
Widget build(BuildContext context) {
// email field
final emailField = TextFormField(
style: Theme.of(context).textTheme.headline6,
autofocus: false,
controller: emailController,
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value!.isEmpty) {
return ('Email obrigatório');
}
// reg expression for email validation
if (!RegExp("^[a-zA-Z0-9 _.-] @[a-zA-Z0-9.-] .[a-z]").hasMatch(value)) {
return ('Insira um email válifo');
}
return null;
},
onSaved: (value) {
emailController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.mail,
color: Color.fromARGB(255, 28, 209, 216),
),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: 'Email',
hintStyle: Theme.of(context).textTheme.headline2,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
//borderSide: BorderSide(color: Colors.pink, width: 5.0),
),
),
);
// password field
final passwordField = TextFormField(
style: Theme.of(context).textTheme.headline6,
autofocus: false,
controller: passwordController,
obscureText: true,
validator: (value) {
RegExp regex = new RegExp(r'^.{6,}$');
if (value!.isEmpty) {
return ('Insira uma password');
}
if (!regex.hasMatch(value)) {
return ('Utilize 6 ou mais carateres');
}
},
onSaved: (value) {
passwordController.text = value!;
},
textInputAction: TextInputAction.done,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.vpn_key,
color: Color.fromARGB(255, 28, 209, 216),
),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: 'Password',
hintStyle: Theme.of(context).textTheme.headline2,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
borderSide: BorderSide(color: Colors.pink, width: 5.0),
),
),
);
// login field
final loginButton = Material(
elevation: 5,
borderRadius: BorderRadius.circular(15),
color: Color.fromARGB(255, 28, 209, 216),
child: MaterialButton(
padding: EdgeInsets.fromLTRB(20, 15, 20, 15),
minWidth: MediaQuery.of(context).size.width,
onPressed: () {
signIn(emailController.text, passwordController.text);
},
child: Text(
'Login',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headline6,
),
),
);
return Scaffold(
// backgroundColor: ,
body: Center(
child: SingleChildScrollView(
child: Container(
// color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(36.0),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 200,
child: Image.asset(
'assets/images/owl_white.png',
fit: BoxFit.contain,
),
),
emailField,
SizedBox(height: 15),
passwordField,
SizedBox(height: 30),
loginButton,
SizedBox(height: 15),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Não tens conta? ',
style: Theme.of(context).textTheme.bodyText1,
),
GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RegistrationScreen(),
),
);
},
child: Text(
'SignUp',
style: Theme.of(context).textTheme.bodyText2,
),
)
],
)
],
),
),
),
),
),
),
);
}
void signIn(String email, String password) async {
if (_formKey.currentState!.validate()) {
try {
await _auth
.signInWithEmailAndPassword(email: email, password: password)
.then((uid) => {
Fluttertoast.showToast(msg: "Login Successful"),
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => DisciplinasScreen())),
});
} on FirebaseAuthException catch (error) {
switch (error.code) {
case "invalid-email":
errorMessage = "Your email address appears to be malformed.";
break;
case "wrong-password":
errorMessage = "Your password is wrong.";
break;
case "user-not-found":
errorMessage = "User with this email doesn't exist.";
break;
case "user-disabled":
errorMessage = "User with this email has been disabled.";
break;
case "too-many-requests":
errorMessage = "Too many requests";
break;
case "operation-not-allowed":
errorMessage = "Signing in with Email and Password is not enabled.";
break;
default:
errorMessage = "An undefined Error happened.";
}
Fluttertoast.showToast(msg: errorMessage!);
print(error.code);
}
}
}
}
the sign up
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import '../../disciplinas/disciplinas_screen.dart';
import '../models/user_model.dart';
class RegistrationScreen extends StatefulWidget {
RegistrationScreen({Key? key}) : super(key: key);
@override
State<RegistrationScreen> createState() => _RegistrationScreenState();
}
class _RegistrationScreenState extends State<RegistrationScreen> {
final _auth = FirebaseAuth.instance;
// our form key
final _formKey = GlobalKey<FormState>();
//editing Controller
final firstNameEditingController = new TextEditingController();
// final secondNameEditingController = new TextEditingController();
final emailEditingController = new TextEditingController();
final passwordEditingController = new TextEditingController();
final confirmPassWordEditingController = new TextEditingController();
String? errorMessage;
@override
Widget build(BuildContext context) {
// first name field
final firstNameField = TextFormField(
style: Theme.of(context).textTheme.headline6,
autofocus: false,
controller: firstNameEditingController,
keyboardType: TextInputType.name,
validator: (value) {
RegExp regex = new RegExp(r'^.{3,}$');
if (value!.isEmpty) {
return ('Insira um Nome');
}
if (!regex.hasMatch(value)) {
return ('Utilize 3 ou mais carateres');
}
return null;
},
onSaved: (value) {
firstNameEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.account_circle,
color: Color.fromARGB(255, 28, 209, 216),
),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: 'Primeiro Nome',
hintStyle: Theme.of(context).textTheme.headline2,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
//borderSide: BorderSide(color: Colors.pink, width: 5.0),
),
),
);
// email field
final emailField = TextFormField(
style: Theme.of(context).textTheme.headline6,
autofocus: false,
controller: emailEditingController,
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value!.isEmpty) {
return ('Email obrigatório');
}
// reg expression for email validation
if (!RegExp("^[a-zA-Z0-9 _.-] @[a-zA-Z0-9.-] .[a-z]").hasMatch(value)) {
return ('Insira um email válifo');
}
return null;
},
onSaved: (value) {
emailEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.mail,
color: Color.fromARGB(255, 28, 209, 216),
),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: 'Email',
hintStyle: Theme.of(context).textTheme.headline2,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
//borderSide: BorderSide(color: Colors.pink, width: 5.0),
),
),
);
// password field
final passwordField = TextFormField(
style: Theme.of(context).textTheme.headline6,
autofocus: false,
controller: passwordEditingController,
obscureText: true,
validator: (value) {
RegExp regex = new RegExp(r'^.{6,}$');
if (value!.isEmpty) {
return ('Insira uma password');
}
if (!regex.hasMatch(value)) {
return ('Utilize 6 ou mais carateres');
}
},
onSaved: (value) {
passwordEditingController.text = value!;
},
textInputAction: TextInputAction.next,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.vpn_key,
color: Color.fromARGB(255, 28, 209, 216),
),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: 'Password',
hintStyle: Theme.of(context).textTheme.headline2,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
//borderSide: BorderSide(color: Colors.pink, width: 5.0),
),
),
);
// confirm password field
final confirmPasswordField = TextFormField(
style: Theme.of(context).textTheme.headline6,
autofocus: false,
controller: confirmPassWordEditingController,
obscureText: true,
validator: (value) {
if (confirmPassWordEditingController.text !=
passwordEditingController.text) {
return ('As palavras-passe não coincidem. Tente novamente.');
}
return null;
},
onSaved: (value) {
confirmPassWordEditingController.text = value!;
},
textInputAction: TextInputAction.done,
decoration: InputDecoration(
prefixIcon: Icon(
Icons.vpn_key,
color: Color.fromARGB(255, 28, 209, 216),
),
contentPadding: EdgeInsets.fromLTRB(20, 15, 20, 15),
hintText: 'Confirma a Password',
hintStyle: Theme.of(context).textTheme.headline2,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15),
//borderSide: BorderSide(color: Colors.pink, width: 5.0),
),
),
);
// signup field
final signUpButton = Material(
elevation: 5,
borderRadius: BorderRadius.circular(15),
color: Color.fromARGB(255, 28, 209, 216),
child: MaterialButton(
padding: EdgeInsets.fromLTRB(20, 15, 20, 15),
minWidth: MediaQuery.of(context).size.width,
onPressed: () {
signUp(emailEditingController.text, passwordEditingController.text);
},
child: Text(
'Sign up',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headline6,
),
),
);
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
leading: IconButton(
icon: Icon(
Icons.arrow_back,
color: Color.fromARGB(255, 28, 209, 216),
),
onPressed: () {
// passing this to our root
Navigator.of(context).pop();
},
),
),
body: Center(
child: SingleChildScrollView(
child: Container(
// color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(36.0),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 200,
child: Image.asset(
'assets/images/owl_white.png',
fit: BoxFit.contain,
),
),
SizedBox(height: 0),
firstNameField,
// SizedBox(height: 15),
// secondNameField,
SizedBox(height: 15),
emailField,
SizedBox(height: 15),
passwordField,
SizedBox(height: 15),
confirmPasswordField,
SizedBox(height: 15),
signUpButton,
],
),
),
),
),
),
),
);
}
void signUp(String email, String password) async {
if (_formKey.currentState!.validate()) {
try {
await _auth
.createUserWithEmailAndPassword(email: email, password: password)
.then((value) => {postDetailsToFirestore()})
.catchError((e) {
Fluttertoast.showToast(msg: e!.message);
});
} on FirebaseAuthException catch (error) {
switch (error.code) {
case "invalid-email":
errorMessage = "Your email address appears to be malformed.";
break;
case "wrong-password":
errorMessage = "Your password is wrong.";
break;
case "user-not-found":
errorMessage = "User with this email doesn't exist.";
break;
case "user-disabled":
errorMessage = "User with this email has been disabled.";
break;
case "too-many-requests":
errorMessage = "Too many requests";
break;
case "operation-not-allowed":
errorMessage = "Signing in with Email and Password is not enabled.";
break;
default:
errorMessage = "An undefined Error happened.";
}
Fluttertoast.showToast(msg: errorMessage!);
print(error.code);
}
}
}
postDetailsToFirestore() async {
// calling our firestore
// calling our model
// sending these values
FirebaseFirestore firebaseFirestore = FirebaseFirestore.instance;
User? user = _auth.currentUser;
UserModel userModel = UserModel();
// writing all the values
userModel.email = user!.email;
userModel.uid = user.uid;
userModel.firstName = firstNameEditingController.text;
await firebaseFirestore
.collection('users')
.doc(user.uid)
.set(userModel.toMap());
Fluttertoast.showToast(msg: 'Conta criada :)');
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => DisciplinasScreen()),
(route) => false);
}
}
CodePudding user response:
Given that once a user logs in they are supposed to be sent to TabsScreen
as per your authwrapper return const TabsScreen();
As per your code once a user is signed in you send them to DisciplinasScreen
Fluttertoast.showToast(msg: "Login Successful"),
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) => DisciplinasScreen())),
Once a user logs in send them to AUth wrapper and let authwrapper figure out where to nav the user
Fluttertoast.showToast(msg: "Login Successful"),
Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (context) =>TabsScreen())),
Navigating them to DisciplinasScreen
causes the 'weird' stuff you are seeing as its built to work within TabsScreen