Flutter buttons not hiding on first click - flutter

I am writing a flutter application and in it, I have join/leave event buttons when the stream comes in it sets the button to either true or false, eg: if a user is in the event it is set to true so the leave button shows up but when I click the leave button I have to click it twice to change before it changes back to the join button when I print the value i can see it change back to true the first click but the UI doesn't change the button back until the second click does anyone know why this is
child: eventStatus
? FlatButton(
child: Text('Leave Event'),
color: Colors.redAccent,
onPressed: () async {
int st = int.parse(eventData.votes);
int newVotes = --st;
await DatabaseService.instance.removeVote(
AuthService.instance.user.uid,
newVotes.toString(),
this.widget.event);
_snackbar.showSnackBarSuccess('OK LEAVE THEN !');
setState(() {
eventStatus = !eventStatus;
print(eventStatus);
});
})
: FlatButton(
child: Text('Join event'),
color: Colors.greenAccent,
onPressed: () async {
int st = int.parse(eventData.votes);
int newVotes = ++st;
await DatabaseService.instance
.vote(newVotes.toString(), this.widget.event);
_snackbar.showSnackBarSuccess('Hey you have friends !');
setState(() {
eventStatus = !eventStatus;
print(eventStatus);
});
}),

Use async/await in other function with Future, and call it in onPressed

Related

adding as favorite conditionally in Flutter

I am using the favorite_button Widget to add items to the list of favorites.
For that matter, I have a listview and for each row, I added the option to add it as a favorite. I also have a condition in the backend that if the number of favorites is more than 10, the responsecode equals to 2 and then shows a dialogbox in the flutter and does not add it to the favorite.
Everything works perfectly. The only problem that I have is that in conditions with more than 10 favorites, when I click, it marks as favorite and then shows the dialog box but I could not find a way to undo this action. However, it does not add it to the list (when I refresh the page, it shows as unmarked). How could I unmark it from marked as favorite, for example, when user closes the showDialog?
Any other approach is also appreciated like simulating the onpressed action to undo the action of favoriting.
Thank you in advance.
StarButton(
isStarred: UserFavorite
.Users!
valueChanged: (_isStarred) {
if (_isStarred == true)
setState(() async {
var resp =
await add(
widget.oauth,
widget.Id,);
if (resp.responseCode ==
2) {
await showDialog(
context: context,
builder:
(alertDialogContext) {
return AlertDialog(
title: Text(
'Limit Reached'),
content: Text(
'You are allowed to add up to 10 sensors as your favorite.'),
actions: [
TextButton(
child: Text(
'Ok'),
onPressed:
() {
Navigator.pop(
alertDialogContext);
},
),
],
);
},
);
}
});
else
setState(() {
delete(
widget.oauth,
widget.Id,
);
});
},
)

Circular progress indicator without Future Builder flutter

How can I add circular progress indicator by the time I press the Elevated Button while I am waiting for my data to show? It would be possible without the need of implementing Future Builder?
ElevatedButton(
onPressed: (() async {
await postML(
_mySelectionFeat1,
_mySelectionFeat2,
_mySelectionFeat3,
_mySelectionValue1,
_mySelectionValue2,
_mySelectionValue3);
}),
child: Text('Post')),
ShowDogCard == false
? const Center(
child: Text('Please select features and values'),
)
: Container(
child: ListCard(
screen: 'ML',
doglist: BreedList,
index: idxBreedListPredicted,
),
),
A way is to have a boolean variable what you set true when you wanna start showing the CircularProgressIndicator, and then set false when you don't want to show it anymore:
bool _loading = true;
build() {
return _loading ? CircularProgressIndicator() : mainWidget();
}
But the best way is to use FutureBuilder. That's what it is for.

I'm trying to use shared_preferences to implement "favorites" functionality in flutter

I'm trying to create a "favorites" function using shared_preferences in flutter.
Use this method to store locally without a database.
The page to use is globals.dart with bool variable, button.dart which is the page selection window (change button color when bookmarked),
And there is a file home0_01.dart with a "favorite icon button (click to add that button to favorites)".
Here I would like to implement it to be stored locally using shared_prefer
But even looking at a lot of example code, it's hard to implement.
There are hundreds of favoriteButton_0_01 in my code because there are so many home0_01.dart files. How should I code in this case?
globals.dart
library prj.com.globals;
bool favoriteButton_0_01 = true;
bool favoriteButton_0_02 = false;
...
button.dart
...
LearnLevelButton(
color: favoriteButton_0_01 ? Colors.orange : Color(0xff7ba6f9),
text: '',
onTap: () async {
await Navigator.pushReplacement(context, MaterialPageRoute(builder: (context){
return home0_01();
}));
},
),
...
home0_01.dart
void delete() async {
setState(() {
favoriteButton_0_01 = false;
print(favoriteButton_0_01);
});
}
void saved() async {
setState(() {
favoriteButton_0_01 = true;
print(favoriteButton_0_01);
});
}
...
actions: <Widget>[
IconButton(
onPressed: favoriteButton_0_01 ? delete : saved,
icon: favoriteButton_0_01
? Icon(Icons.bookmark_rounded, color: Colors.yellow[800], size: 30)
: Icon(Icons.bookmark_add_outlined, color: Colors.yellow[800],size: 30),
),
],
...
You can watch this tutorial in order to accomplish something like that: https://www.youtube.com/watch?v=TRB0qZ2XaO4. It's basically the same idea. Press a button and add it somewhere else. Hope this might help.

How do I interact with UI and async functions by a button press?

So I have a login button that would initiate an async function logMeIn() for logging in, which returns a Future<bool> indicating if logging in was successful.
What I want to achieve is after pressing the button, the text within the button would change into a CircularProgressIndicator, and become plain text when logMeIn() has finished.
I know that I could use a FutureBuilder for one-time async tasks, but I simply can't think of a way to use it here.
How am I supposed to achieve this?
Thanks in advance.
Edit
I didn't provide more information because I'm pretty sure it wasn't how it's supposed to be done. But I'd share what I tried whatsoever.
My original button looks somewhat like this:
RaisedButton(
child: Text("Login")
)
I have a async login function that returns a Future<bool> which indicates if the login is successful or not.
Future<bool> logMeIn() async {
// login tasks here
}
What I want to do is to change the button to the following and run logMeIn() when I press the button, and change it back to the plain text version after it's finished:
RaisedButton(
child: CircularProgressIndicator()
onPressed: () {}
)
What I tried
I tried adding a logging_in boolean as a flag to control it, here I call the button with plain text StaticButton(), the other named ActiveButton:
Then I wrapped the ActiveButton with a FutureBuilder:
logging_in ? FutureBuilder(
future: logMeIn(),
builder: (_, snapshot) {
if(snapshot.hasData)
setState(() {
logging_in = false;
});
else
return ActiveButton();
}
) : StaticButton();
and when I pressed the button it would setState and set logging_in = true.
StaticButton:
RaisedButton(
child: Text("Login"),
onPressed: () {
setState(() {
logging_in = true;
});
}
)
The above is what I tried. Should accomplish the effect, but is definitely not elegant. Is there a better way to achieve this?
What you have isn't that far off. You have a logging_in variable that tells you when to show the CircularProgressIndicator already, which is a good start. The only thing is that FutureBuilder has no use here. It's meant for retrieving data from Futures that need to be displayed in the UI.
What you need to do is call logMeIn in the onPressed of your "Static button" as shown here:
StaticButton:
RaisedButton(
child: Text("Login"),
onPressed: () async {
setState(() {
logging_in = true;
});
await logMeIn();
setState(() {
logging_in = false;
});
}
)
You don't need to switch out the whole button when logging_in changes, just the child of the button.
StaticButton(with child switching):
RaisedButton(
child: logging_in ? CircularProgressIndicator() : Text("Login"),
onPressed: () async {
setState(() {
logging_in = true;
});
await logMeIn();
setState(() {
logging_in = false;
});
}
)
You also probably want to add another bool to prevent multiple clicks of the button while its loading. As a note in using FutureBuilder and essentially any other builder in flutter, you always need to return a widget from the builder function, which your current implementation does not do.

How to handle progress indicator upon canceling google sign-in dialog?

When user clicks on Google Sign in button, the progress indicator is set to true and the app shows dialog to select user accounts from. If user clicks outside of the dialog or system back button, the progress indicator keeps showing.
Where and how do I set the _isLoading = false so that the progress indicator goes away ?
Container(
padding: EdgeInsets.all(_isLoading ? 20.0 : 0.0),
width: 75,
height: 75,
child: _isLoading
? CircularProgressIndicator()
: IconButton(
icon: Image.asset('assets/google.png'),
onPressed: () => _handleGoogleSignIn()),
)
...
Future<Null> _handleGoogleSignIn() async {
setState(() {
_isLoading = true;
});
LoginUtils().handleGoogleSignIn().then((firebaseUser) {
_postSignInAction(firebaseUser);
}).catchError((exception) {
_handleLoginException(exception);
});
}
This depends on what exactly LoginUtils().handleGoogleSignIn() does. Given that it is a Future, if what it does is display the dialog to select the Google account, it should complete as soon as the dialog is dismissed. I would expect it to complete successfully, with firebaseUser being null - this is the default behavior when popping routes by pressing back as well.
You should therefore simply have to add the following:
if (firebaseUser == null) {
setState(() {
_isLoading = false;
});
}
If however that Future does not complete at all when the dialog is dismissed, then that's the problem you need to solve.