How to display time on buttons in Flutter - flutter

Requirement:
I have 2 buttons, I want when I click on button 1 its text should be replaced by the current time, and the same for button 2.
Problem:
The problem is when I click on button 1 its text change to the current time, but when I click on button 2 after a few minutes its text changes to the same time that button 1 has.
Here is my code:
void initState() {
// TODO: implement initState
super.initState();
_getTime();
}
void _getTime() {
final String formattedDateTime =
DateFormat('kk:mm:ss').format(DateTime.now()).toString();
setState(() {
getTime = formattedDateTime;
print(getTime[0]);
});
}
var timeInText="Time in";
var timeOutText="Time out";
\\button 1
RoundedButton(icon: Icon(Icons.timer,color: Colors.white),
text:timeInText,
bgcolor: Colors.blue[500],
press:(){
setState(() {
timeInText=getTime;
});
})
//button 2
RoundedButton(icon: Icon(Icons.timer,color: Colors.white),
text:timeoutText,
bgcolor: Colors.blue[500],
press:(){
setState(() {
timeoutText=getTime;
});
})
please help to fix it. thanks

You call _getTime() only in initState. Time is stored on initialization and never updated after that. Since it's never updated it's showing the same time constantly.
To fix that add a _getTime() call to both of your onPressed functions like this:
onPressed: () {
_getTime();
setState(() {
timeoutText = getTime;
});
}),

You get the time one, when the button clicked. You have to write your method codes in setState too i think. And get the current time 🤔 i hope it will help

Related

How to wait for action of user in Flutter?

I have a problem with a function. I need to realize a func which will be work correctly when user taps on button. I need to froze this func and wait for user's action. (tap on button).
Maybe y have already to faced to the same prob
void submitAnswer(String submittedAnswer) async {
timerAnimationController.stop();
if (!context.read<QuestionsCubit>().questions()[currentQuestionIndex].attempted) {
context.read<QuestionsCubit>().updateQuestionWithAnswerAndLifeline(context.read<QuestionsCubit>().questions()[currentQuestionIndex].id, submittedAnswer);
updateTotalSecondsToCompleteQuiz();
//change question
await Future.delayed(Duration(seconds: inBetweenQuestionTimeInSeconds));
if (currentQuestionIndex != (context.read<QuestionsCubit>().questions().length - 1)) {
updateSubmittedAnswerForBookmark(context.read<QuestionsCubit>().questions()[currentQuestionIndex]);
timerAnimationController.stop();
//I want to froze this part and wait for user's action.
//When user taps on 'next', it continues working.
//////////////////////////////////////////////////////
changeQuestion();
if (widget.quizType == QuizTypes.audioQuestions) {
timerAnimationController.value = 0.0;
showOptionAnimationController.forward();
} else {
timerAnimationController.forward(from: 0.0);
}
//////////////////////////////////////////////////////
} else {
updateSubmittedAnswerForBookmark(context.read<QuestionsCubit>().questions()[currentQuestionIndex]);
navigateToResultScreen();
}
}
}
When user taps on button, this func continue working
TextButton(
child: Text("Next >>"),
onPressed: () {
setState(() {
callMyFun();
});
//global.setMyStatus == true;
}
)
Disclaimer: while this will solve your problem, it's far away from
good practice, you should split your function into two
different ones
You can achieve that using Completer
Example:
Completer<void>? nextButtonCompleter;
Future<void> submitAnswer(String submittedAnswer) async {
// Your code (removed to make answer short)
// ...
//I want to froze this part and wait for user's action.
//When user taps on 'next', it continues working.
final completer = new Completer<void>();
nextButtonCompleter = completer;
// This line will wait until onPressed called
await completer.future;
// your other code
}
And in your button
TextButton(
child: Text("Next >>"),
onPressed: () {
setState(() {
callMyFun();
});
nextButtonCompleter?.complete();
nextButtonCompleter = null;
}
)

Flutter Function to reload variable

I wanted to make like a currency converter so I created this,
final montant = TextEditingController()..text = '500';
double convertEuro(montant) {
double convtEur = (double.parse(montant.text) / 3.2);
return convtEur;
}
double converted = 0;
I had a problem with my function here because the function when the screen loads it's null so I created that converted variable ( It's a stupid move I know at least to get rid of the error on my screen but only showing the initial value from my textController above
Text(
"${double.parse(montant.text)}" +
"DT = $converted" +
" €",
)
Anyway, the function is triggered when a button is pressed.
onPressed: () {
if (_formKey.currentState.validate()) {
converted = convertEuro(montant);
}
},
Can anyone help me how to change that variable value and make it change on my screen when the button is pressed?
You can do like this:
setState(() {
converted = convertEuro(montant);
});
In this, you're basically doing a rebuild of the widget.
Thus to implement this in your code, put setState under the onPress:
onPressed: () {
if (_formKey.currentState.validate()) {
setState(() {
converted = convertEuro(montant);
});
}
},

Flutter: How to change button depending on state?

I'm trying to do the following: I have a container, and a button inside it and upon clicking on the button (onPressed) I would like to display a different button (aka. change the widget).
Would appreciate some help in doing so, thanks in advance!!
define the initial value for example
double paddingLeft = 10.0;
And after clicking on that button update the state with actual value Like
setState(() {
paddingLeft = 20.0
});
There might be different ways. One of the methods is:
bool _val = true;
Container(
child: _val ? button1( // when _val is true button1 will be the child of container. So it will be visible.
onPressed: () {
_val = !_val;
setState(() {
});
})
: button2(), // when _val is false button2 will be the child of container. So it will be visible.
);
First of all, you need to make sure that the class you are in extends a StatefulWidget, because that means that the class will rerender when a state changes, which is what you need to be able to show another button.
Then you can define a state bool _showButton1 = true;
In your Container you can then have something like this:
Container(
child: _showButton1 ? _button1() : _button2();
)
(Meaning: if _showButton1 is true, show the widget _button1, else show _button2)
where _button1 would look something like this:
Widget _button1() {
return Button(
onPressed: () => setState(() {
_showButton1 = false;
})
);
}
(Meaning: when this button is pressed, update the state _showButton1 to false and rerender this class --> button 2 will be shown)

I need to press the button 2 times in order to function (flutter)

I have a problem implementing a login button, when I press it, it will not function at first, but when I press it again (same value fields) it works.
here's my code
Button:
Center(child: RaisedButton(onPressed: (){
setState(() {
onPressedLogin(userName.text,password.text);
});
}
The OnPressedLogin():
void onPressedLogin(String userName,String password) async{
bool isValid = false;
var value = await dataBaseHelper.getUserList();
for(User userOB in value){
//print(userOB.password+" "+password),
if(userName == userOB.username && password == userOB.password) {
isValid = true;
this.password.clear();
this.userName.clear();
inputTextColor = Colors.grey[850];
invalidCredentials = "";
print("YES");
//Navigator.push(context, MaterialPageRoute(builder: (context) => Home()));
break;
}
}
if(!isValid){
inputTextColor = Colors.red[800];
invalidCredentials = "Invalid Credentials";
}
You are using a Future but in setState() you are not waiting for it so that's way it work in the second press (the value take time to change).
To make it work with single press you have to a wait the Future to complete before rebuilding, here how:
First change the return type of the function
Future<void> onPressedLogin(String userName,String password)
Then in the RaisedButton
onPressed: () async {
await onPressedLogin(userName.text,password.text);
setState(() {});
},
The moment you setState(), the UI will refresh!
Probably that's the issue, let me explain:
What you should do is to call your function before setState(), so that the screen is refreshed with the new info.
Center(child: RaisedButton(onPressed: (){
onPressedLogin(userName.text,password.text);
setState(() {
//Variables that change for the refresh.
});
}
In your specific case, I don't see the need for SetState() as you are only printing values in log, not changing the UI.
Hope it is helpful.

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.