flutter:: Can I use conditional statements inside a button or widget? - flutter

This is my code. I want to get a variable called "favorite" from the Video0_02 file and change the color to yellow if true and to blue if false. I don't know how to write the code because the if statement doesn't work.
How do I solve this?
LearnLevelButton(
color: Colors.yellow,
onTap: () async {
await Navigator.push(
context, MaterialPageRoute(builder: (context) {
return Video0_02();
//Level newLevel = await gameBloc.setLevel(index + 1);
//Navigator.of(context).push(GamePage.route(newLevel));
}));
},
),

Try with this
LearnLevelButton(
color: favorite? Colors.yellow:Colors.blue,
onTap: () async {
await Navigator.push(
context, MaterialPageRoute(builder: (context) {
return Video0_02();
//Level newLevel = await gameBloc.setLevel(index + 1);
//Navigator.of(context).push(GamePage.route(newLevel));
}));
},
),

There are several ways you can use to handle the logic.
Use Dart's ternary operator. Something like this:
...
// Remember to check in case your `favorite` variable is null, set it to false
LearnLevelButton(
color: (favorite ?? false) ? Colors.yellow : Colors.blue,
...
),
Use a function to handle the logic:
LearnLevelButton(
color: getColor(favorite),
...
),
// The function
Color getColor(bool favorite) {
if (favorite ?? false) {
return Colors.yellow;
}
return Colors.blue;
}
Other way is immediate anonymous function or use switch/case in your separate function when there are more than 2 values to consider. But these 2 methods should be enough to get you started! ;)

Related

How distinguish inner context?

I wrote the code like data: (data){Navigator.of(context).pop();},//here to pop showDialog but actually other Navigator.of(context) was popped and figured out that I should distinguish inner context in builder: (context) { //here2 from outer context but could not reach how to do that. Would somebody please give me some advise to solve this ?
final authC = ref.watch(authFutureProvider);
authC.when(
data: (data){Navigator.of(context).pop();},//here
error: (error, stackTrace) {},
loading: () {
final loading =
WidgetsBinding.instance.addPostFrameCallback((_) {
showDialog(
barrierDismissible: false,
context: context,
builder: (context) { //here2
return const Center(
child: CircularProgressIndicator(),
);
}
);
});
},
);
Well, you can easily define different BuildContexts by giving them different names, like this:
#override
Widget build(BuildContext parentContext) {
final authC = ref.watch(authFutureProvider);
authC.when(
data: (data){Navigator.of(parentContext).pop();},//here
error: (error, stackTrace) {},
loading: () {
final loading =
WidgetsBinding.instance.addPostFrameCallback((_) {
showDialog(
barrierDismissible: false,
context: parentContext,
builder: (context) { //here2
return const Center(
child: CircularProgressIndicator(),
);
}
);
});
},
);
return Widget();
}
However, that won't change the fact that the context I've named "parentContext" is the parent context! This is the context sent TO the Dialog, not the context of the Dialog itself.
If you want to pop whichever context is on top at the moment, you can define a GlobalKey variable like this:
//global.dart
import 'package:flutter/material.dart';
class GlobalVariable {
static final GlobalKey<NavigatorState> navState = GlobalKey<NavigatorState>();
}
Then, you can pop the current context like this, from anywhere:
import 'global.dart';
void func(){
Navigator.pop(GlobalVariable.navState.currentContext!);
}
That should pop the Dialog IF the Dialog is currently on top...
But of course, if some other BuildContext is on top, then that will be popped, instead. 😏 So make sure you write the proper conditions for that.
Edit:
You could also use popUntil(). If this happens to be the first screen, you can just write:
#override
Widget build(BuildContext parentContext) {
final authC = ref.watch(authFutureProvider);
authC.when(
data: (data){Navigator.popUntil(context, (route) => route.isFirst);},//here
error: (error, stackTrace) {},
loading: () {
final loading =
WidgetsBinding.instance.addPostFrameCallback((_) {
showDialog(
barrierDismissible: false,
context: parentContext,
builder: (context) { //here2
return const Center(
child: CircularProgressIndicator(),
);
}
);
});
},
);
return Widget();
}
If not, then it's a bit more complicated to make it pop back to this particular screen... But you could use routeSettings, for example.
I strongly not recommend WidgetsBinding.instance.addPostFrameCallback to show loading because it takes time to render, so your app will load a loading function. It will make End-user can do multiple clicks on the button because the loading has not rendered yet.
this package is verylight and easy to use, the dismiss and show even different from regular widget, so you will not accidentally close your screen because wrong logic or back-end handler failure.
class LoadingExample {
showLoadingExample(){
EasyLoading.instance
..displayDuration = const Duration(milliseconds: 2000)
..indicatorType = EasyLoadingIndicatorType.fadingCircle
..loadingStyle = EasyLoadingStyle.dark
..indicatorSize = 45.0
..radius = 10.0
..progressColor = Colors.yellow
..backgroundColor = Colors.green
..indicatorColor = Colors.yellow
..textColor = Colors.yellow
..maskColor = Colors.blue.withOpacity(0.5)
..userInteractions = true
..dismissOnTap = false
..customAnimation = CustomAnimation();
}
dismissExampleLoading(){
EasyLoading.dismiss();
}
}
to call it simply do: *I recommend OOP so you can modify it in 1 place when you need.
LoadingExample().showLoadingExample();
or
LoadingExample().dismissExampleLoading();
even you accidentally call show or dissmiss multiple time, the loading will not stack, and it will just recall or reset the animation. So your app will not crash
Flutter_easyloading

Why using <Null> after showDialog?

Here I'm rendering an AlertDialog inside showDialog to display when error thrown from provider file. But that didn't work first time( Seems like stuck in catchError block, didn't execute future of catchError), Then I told to add <Null> after showDialog. That worked But How, What is changed, what it means?
Here is the code
if (_editedProduct.id == null) {
Provider.of<Products>(context, listen: false)
.addProduct(_editedProduct)
.catchError((error) {
return showDialog<Null>( //Here is that Null I didn't understand
context: context,
builder: (ctx) {
return AlertDialog(
title: Text('ERROR'),
content: Text('Error Occured'),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('I GOT IT'),
)
],
);
});
}).then((_) {
print('THEN');
setState(() {
isLoading = false;
});
Navigator.of(context).pop();
});
} else {
Provider.of<Products>(context, listen: false)
.updateProduct(_editedProduct.id, _editedProduct);
Navigator.of(context).pop();
}
}
Nb: isLoading true shows a circluarProgressIndicator()
From the Official Docs
Returns a Future that resolves to the value (if any) that was passed to Navigator.pop when the dialog was closed.
The place where you sent Null indicates the type of data the Future will return.
By using Null you are indicating that the Future won't return any data, this tell your program not to wait for the possible value that might be returned.
Suppose in your dialog user has to pick 2 numbers and you want the picked number to be returned to the place where you called the showDialog() function then you'll use int instead of Null.
Something like
showDialog<int>(...)

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.

Why here the condition in the if statement is not able to satisfy

here the userPassword.text and userName.text are the texteditingcontrollers which contain the value that user has just entered . and then i am comparing them with already saved values in the user object. i am not able to do it. but when i compare using a constant string it is working like if (userName.text == "hardik" && userPassword.text == "hardik#1"){ } this code is working. but not when i compare using user model .
Please help...
MyTextButton(
buttonName: 'Sign In',
onTap: () {
for (var user in registeredUsers) {
if ( user.userName == userName.text && user.userPassword ==
userPassword.text) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomeScreen(registeredUsers),
),
);
} else {
print("Invalid Credintials");
}
}
},
bgColor: Colors.white,
textColor: Colors.black87,
),

Flutter: Changing boolean value to true onPressed

I am new to Flutter and can't figure out why my boolean variable clickedLike isn't changing to true.
I declare this outside my Column, with the initial value false in a StatefulWidget class.
IconButton(
onPressed: () async {
setState(() {
likeColor = Colors.blue;
if (clickedLike == false) {
numLikes++;
FirebaseFirestore.instance
.collection('board')
.doc(docID)
.update({'likes': numLikes});
clickedLike = true;
} else {}
});
},
icon: Icon(Icons.thumb_up, color: likeColor)
//color: Colors.blue,
),
I have omitted the rest of the children widgets, as they are irrelevant. Any help would be appreciated. Thanks.
if (!clickedLike) {
numLikes++;
FirebaseFirestore.instance
.collection('board')
.doc(docID)
.update({'likes': numLikes});
clickedLike = !clickedLike;
}
try this ?