Reputation: 459
I'm trying to figure out how to hide my login/signup buttons if a user is signed in or out.
I've looked into VISIBILITY and GONE, either one will work. However, I can't find any tutorials that match what I'm trying to accomplish.
Here's some code snippets for what I'm trying to accomplish:
Edit from original post:
In authentication.dart (only functions):
loginUser(context) async {
formkey.currentState.save();
if (formkey.currentState.validate()) {
await _auth
.signInWithEmailAndPassword(email: _email, password: _password)
.catchError((e) {
home.changeState(null);
Fluttertoast.showToast(
msg: "Invalid email and/or password. Please try again",
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.TOP,
timeInSecForIos: 5,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0
);
}).then((newUser) {
var now = new DateTime.now();
Firestore.instance
.collection('users')
.document(newUser.uid)
.collection('userInfo')
.document('userInfo')
.setData({
'Last login': now,
}).catchError((e) {
Fluttertoast.showToast(
msg: "Update user failed: $e",
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.TOP,
timeInSecForIos: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0
);
});
welcomeUser();
Navigator.of(context).pop();
});
}
final user = await getSignedInUser();
home.changeState(user);
}
getSignedInUser() async {
mCurrentUser = await FirebaseAuth.instance.currentUser();
if(mCurrentUser == null || mCurrentUser.isAnonymous){
return null;
}
else{
return mCurrentUser;
}
}
signOutUser () async{
await _auth.signOut();
final user = await getSignedInUser();
home.changeState(user);
}
HomeScreen home; //create instance of homescreen class, so I could call my function
In loginScreen (piece to create button to login):
Expanded(
child: OutlineButton(
child: Text("Login "),
onPressed: () =>
loginUser(context)),
flex: 1,
),
homeScreen class (omitted irrelevant functions):
class HomeScreen extends State<MyApp> {
FirebaseUser currentUser; //not sure what to initialize this to upon loading app because user might still be signed in.
final formkey = GlobalKey<FormState>();
@override
Widget build(BuildContext context){
return MaterialApp(
home: Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(title: Text("HikeLocator"), backgroundColor: Colors.green[700],
),
body: Container(
margin: EdgeInsets.all(20.0),
child: Form(
key: formkey,
child:
Column(
children: <Widget>[
distanceFromUser(),
lengthOfTrail(),
numOfResults(),
Container(
margin: EdgeInsets.only(top: 25.0),
),
submitButton(),
// loginButton(),
//signupButton(),
//logoutButton(),
//profile(),
] + (currentUser == null ? [
loginButton(),
signupButton(),
] : [ // logged in? show the following widgets
logoutButton(),
profile(),
]),
),
)
),
),
);
}
Widget loginButton() {
return RaisedButton(
color: Color.fromRGBO(58, 66, 86, 1.0),
child: Text("Log In", style: TextStyle(color: Colors.white)),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => LogInScreen()),
);
},
);
}
Widget logoutButton(){
return RaisedButton(
color: Color.fromRGBO(58, 66, 86, 1.0),
child: Text("Log Out", style: TextStyle(color: Colors.white)),
onPressed: () async {
await signOutUser();
}
);
}
Widget signupButton() {
return RaisedButton(
color: Color.fromRGBO(58, 66, 86, 1.0),
child: Text("Sign Up", style: TextStyle(color: Colors.white)),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SignUpScreen()),
);
},
);
}
changeState(value){
setState(() {
this.currentUser = value;
});
}
}
I have a function I wrote called getSignedInUser(). If there is none, it returns null. I'm new to flutter. Specified above in comments show the buttons that are supposed to be visibile in certain cases. Thanks for any help.
Upvotes: 1
Views: 8921
Reputation: 459
Ok I found a workaround. Have my landing page as login, with a button that says continue as guest. When I click login, it take me back to homescreen, but I send a value into the constructor as 1. If I click continue as guest, it sends value of 0. Then I check if that value is 0 or 1 to determine if I should render the widgets. I'm having another issue dealing with formkeys and page routes, but I'll post a separate question on that. Thanks for your help guys
Upvotes: 0
Reputation: 18177
I would go with this:
Widget loginButton() {
return getSignedInUser() == null
? RaisedButton(
color: Color.fromRGBO(58, 66, 86, 1.0),
child: Text("Log In", style: TextStyle(color: Colors.white)),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => LogInScreen()),
);
},
)
: Container();
}
If the user is signed-in, return an empty container, otherwise, return the login button. You can do the same in other functions that return a widget.
You could also wrap your login button in Opacity
widget and set opacity
to 0.0 to make it hidden, but it will still occupy space.
Update: I've prepared the following example to demonstrate a simple login page. The getUser
function simulates a function that authenticates the user and returns the username (after two seconds) if login is successful.
import 'package:flutter/material.dart';
class LoginPage extends StatefulWidget {
@override
LoginPageState createState() {
return new LoginPageState();
}
}
class LoginPageState extends State<LoginPage> {
String user;
Future<String> getUser() {
return Future.delayed(
Duration(seconds: 2),
() {
return "john";
},
);
}
void login() async {
final user = await getUser();
setState(() {
this.user = user;
});
}
void logout() {
setState(() {
this.user = null;
});
}
Widget _buildLoginButton() {
return user == null
? RaisedButton(
onPressed: login,
child: Text("Login"),
)
: Container();
}
Widget _buildLogoutButton() {
return (user != null)
? RaisedButton(
onPressed: logout,
child: Text("Logout"),
)
: Container();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Login"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_buildLoginButton(),
_buildLogoutButton(),
],
),
),
);
}
}
Upvotes: 4