I am struggling to hide SpeedDialChild, when my noDoctorReply == false. I can't use if else conditions. I tried to code like below.
noDoctorReply == false
? SpeedDialChild(
child: Icon(Icons.stop_screen_share_outlined),
backgroundColor: Colors.green,
label: 'Complete Conversation',
labelStyle: TextStyle(fontSize: 18.0),
onTap: () {
_completeDialog();
},
)
: SpeedDialChild(),
But it got me to here.
Is there any way to hide this? Thank you.
EDIT: I used package called flutter_speed_dial.
You can use just if conditional state. While else is never needed to show up.
if(noDoctorReply) showMyWidget()
You can also check Visibility widget.
Related
I want to disable a button untill all the required fields are filled. I found similar questions here but all answers are based on making the onPressed property to null. But it does not disable the tap effect.
I want something like this. On disabled mode, clicking on the button won't even cause a Tap effect. Can someone help with a solution?
For a limited number of widgets, you can wrap them in a widget IgnorePointer: when its ignoring property is set to true, the sub-widget (actually, the entire subtree) is not clickable.
IgnorePointer(
ignoring: true, // or false
child: CustomButton(
onPressed: _login,
child: Text("Login"),
),
)
checkout this widget.set absorb to true when the required field is empty or is not validated.
https://api.flutter.dev/flutter/widgets/AbsorbPointer-class.html
In the textField add
onChanged : (val){ setastate((){});}
You mustbe already having a TextEditingController for the textfield. For example i shall name it phoneTextController.
Now in the button check the condition
phoneTextController.text.length > 10
For example
Inkwell(
onTap:(){
if(phoneTextController.text.length > 10){
SendOtp()
}
}
child: Container(
color: phoneTextController.text.length > 10 ? Colors.blue : Color.blue.withOpacity(0.5),
)
)
If you're using one of Flutter's built-in button Widgets, setting the onTap to null should automatically disable the button and its effect. Now all that remains is to conditionally do this during your build. Say, like the other answer, your TextEditingController is named phoneTextController:
ElevatedButton(
child: Text('Next'),
onTap: phoneTextController.text.length > 10 ? () => goToNextPage() : null,
),
Which will automatically enable the button and add the callback as soon as the condition is met (in this example, the input length is >10.
What is MaterialStateProperty in ButtonStyle?
ThemeData(
textButtonTheme: TextButtonThemeData(
style: ButtonStyle(
backgroundColor: , //?
),
),
),
The purpose of MaterialStateProperty is to make it possible to specify different styles for different states.
For example, if we want a button that's usually blue, but turns green when it's pressed, and enlarges its texts at the same time, we can use MaterialStateProperty.resolveWith to do exactly that.
ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.resolveWith((states) {
// If the button is pressed, return green, otherwise blue
if (states.contains(MaterialState.pressed)) {
return Colors.green;
}
return Colors.blue;
}),
textStyle: MaterialStateProperty.resolveWith((states) {
// If the button is pressed, return size 40, otherwise 20
if (states.contains(MaterialState.pressed)) {
return TextStyle(fontSize: 40);
}
return TextStyle(fontSize: 20);
}),
),
child: Text("Changing Button"),
onPressed: () {},
)
In addition to checking whether the button is being "pressed", MaterialStateProperty also supports: disabled, dragged, error, focused, hovered, pressed, scrolledUnder, selected. Note that it's possible to have multiple states at once. For example, a button can be both "disabled" & "hovered" at the same time. With MaterialStateProperty you can customize its appearance when that happens.
"Is there a clean way to resolve multiple states at once?"
The Flutter API documentation provides a nice clean pattern for resolving any of multiple states at one time. For example, if you want to respond the same way to all interactive states you could define a method like this:
Color getColor(Set<MaterialState> states) {
const Set<MaterialState> interactiveStates = <MaterialState>{
MaterialState.pressed, // Any states you want to affect here
MaterialState.hovered,
MaterialState.focused,
};
if (states.any(interactiveStates.contains)) {
// if any of the input states are found in our list
return Colors.blue;
}
return Colors.red; // default color
}
Then later in the button widget, simply assign that method as the resolver for the backgroundColor:
TextButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.resolveWith(getColor),
),
onPressed: () {},
child: const Text('Changing Button'),
);
Play with the full example in Dart Pad.
"Okay, but I just want a red button."
Sure, it seems like you can use: MaterialStateProperty.all(Colors.red) to make it red in all cases. But that's probably NOT what you want. For example, when the button is disabled, do you still want it to be red?
See, "all" means "all". This is not good.
So what, are we stuck dealing with MaterialStateProperty and checking for disabled states all day?
Thankfully, no. There's a better way:
If you are using ElevatedButton, you can use ElevatedButton.styleFrom as a base style. Similarly, if you are using TextButton, you can use TextButton.styleFrom. From there, you can easily modify some of the styles.
Code:
ElevatedButton(
style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
child: Text("Red Button"),
onPressed: () {},
)
That's it, you just pass in a Color class. Super easy, no MaterialStateProperty involved. And it automatically handles edge cases for you.
I am assuming that you want to know how to assign a color to the backgroundColor parameter of the ButtonStyle widget. If that is the case then just type something like this:
backgroundColor: MaterialStateProperty.all(Colors.green),
OR
backgroundColor: MaterialStateProperty.all(Color(0xFF5D5F6E)),
Interface for classes that resolve to a value of type T based on a widget's interactive "state", which is defined as a set of MaterialStates.
Material state properties represent values that depend on a widget's material "state". The state is encoded as a set of MaterialState values, like MaterialState.focused, MaterialState.hovered, MaterialState.pressed. For example, the InkWell.overlayColor defines the color that fills the ink well when it's pressed (the "splash color"), focused, or hovered. The InkWell uses the overlay color's resolve method to compute the color for the ink well's current state.
ButtonStyle, which is used to configure the appearance of buttons like TextButton, ElevatedButton, and OutlinedButton, has many material state properties. The button widgets keep track of their current material state and resolve the button style's material state properties when their value is needed.
Code Example:
Widget build(BuildContext context) {
Color getColor(Set<MaterialState> states) {
const Set<MaterialState> interactiveStates = <MaterialState>{
MaterialState.pressed,
MaterialState.hovered,
MaterialState.focused,
};
if (states.any(interactiveStates.contains)) {
return Colors.blue;
}
return Colors.red;
}
return TextButton(
style: ButtonStyle(
foregroundColor: MaterialStateProperty.resolveWith(getColor),
),
onPressed: () {},
child: Text('TextButton'),
);
}
A simple way to use it:
MaterialStateProperty.all(Colors.green) // Whatever value you want
To get more you can check official documentation of Material state properties made by the flutter team.
It is used to calculate the value depending on the current interactive state of the button, which can be hovered, pressed, focused,... (full list here).
If you want a fixed value, you can use MaterialStateProperty.all(YOUR_VALUE), this value will be applied to all button states.
You can find more information here: https://api.flutter.dev/flutter/material/MaterialStateProperty-class.html
My problem is simple. I was building a ListTile from the list of documents I get from firebase by iterating through the results. The ListTile contains a leading icon, a title, and a trailing favorite IconButton. The list tile shows perfectly as I want it to. But the problem arises when I try to change the color of the IconButton while a user taps on it. For some reason, the code I wrote isn't doing the trick. What i tried to do was to set the value of the IconButton's color by a ternary which uses a class variable named isFavorited. What i wanted it to do is change the color of the IconButton when i tap on that same IconButton. Here is my code block:
// Builds a tile for each brought up names of taxistops
if (retrievedData.isNotEmpty) {
retrievedData.forEach((element) {
if (element.contains(query) ||
element.contains(query.toUpperCase()) ||
element.contains(query.toLowerCase())) {
ListTile listTile = ListTile(
leading: Icon(Icons.local_taxi),
title: Text(element),
trailing: IconButton(
icon: isFavorited
? Icon(
Icons.star,
color: Colors.amber[400],
)
: Icon(Icons.star_border),
onPressed: () => {
setState(() {
isFavorited = true;
}),
addToFavorite()
},
),
onTap: () => close(context, element),
);
searchedTiles.add(listTile);
}
});
}
Any help is appreciated! Thank you in advance!
I think the problem is because you are adding the widget in the list you should preview it directly inside the widget father (ListView) so it can do the setState correctly and not inside a list you created as a data structure to store elements.
I think that's the issue if it still doesn't work I would need to see how you are showing the list.
Might be a very obvious question, but I need to add a TextStyle in a conditional statement, but it seems to not be applying it. This is what I tried:
Text((() {
if (contract.active == true) {
TextStyle(fontSize: 18);
return 'active';
}
return 'inactive';
}())),
It is not applying the textStyle. thank you.
You can use ternary operator:
Text(
'dummy text',
style: contract.active == true ? TextStyle(color: Colors.red): TextStyle(color:Colors.blue),
)
I added this for only TextStyle, you can do it for Text if you want.
And one thing, contract.active is already bool you don't need to check its equality, you can use contract.active instead of contract.active == true.
You can change text like this:
Text(
contract.active ? 'active' :'inactive'
style: contract.active ? TextStyle(fontSize: 18) : TextStyle()
)
You are using an immediate anonymous function there. The first parameter of Text widget expects a string and your anonymous function returns that. The TextStyle object that you've created inside the function body doesn't do anything.
You need to change your implementation to (using immediate anonymous function):
Text(
(() {
if (contract.active) {
return "Active";
}
return "Inactive";
}()),
style: (() {
if (contract.active) {
return TextStyle(fontSize: 18);
}
return null;
}())
),
But the above code looks very odd, you can simply achieve that using ternary operator:
Text(contract.active ? "Active" : "Inactive",
style: active ? TextStyle(fontSize: 18) : null),
hello there i have this classes
ServicesIndex
ServicesCreate
ServicesEdit
what i want to do is on click of button in either Create or Edit i want to pop all alerts and pages and push replacement to ServicesIndex
what should i do exactly ?
the button which will be clicked in Services Create and Edit
showSuccessMessage(context) {
var responsivenessController = ResponsivenessController(context);
Alert(
context: context,
type: AlertType.success,
style: AlertStyle(titleStyle: Theme
.of(context)
.textTheme
.bodyText1
, descStyle: Theme
.of(context)
.textTheme
.bodyText1),
title: translator.currentLanguage == 'ar' ? 'تم الحفظ'
: 'Stored Successfully',
desc: translator.currentLanguage == 'ar' ? 'تمت عملية الحفظ بنجاح'
: 'Information Stored Successfully',
buttons: [
DialogButton(
child: Text(
translator.currentLanguage == 'ar' ?
"المتابعة"
: 'OK',
style: TextStyle(color: Colors.white,
fontSize: responsivenessController.bodyFont),
),
onPressed: () {
Navigator.pop(context);
}
)
],
).show();
}
its all in on pressed event what code do you suggest ?
about the stack of elements its
Index
---Create
---SuccessMessage
---Edit
---SuccessMessage
so the action should pop 2 times and push replacement
i can of course hard code like this
onPressed: () {
Navigator.pop(context);
Navigator.pop(context);
Navigator.pop(context);
Navigator.pushReplacement(context, MaterialPageRoute(
builder: (BuildContext context) => className
));
}
but i want something more flexible like just pass the Class name and it will return to it while popping everything before it
Note : Named Routes will not work because every page requires some parameters that will be passed later in the process i can't fetch them all in main.dart i will cause slow performance
If you know how many pop you need to call then simply use popUntil with a counter.
Code
// In this case we want to pop 4 times
void onPressed() {
int count = 0;
Navigator.popUntil(context, (route) => count++ == 4);
}