I have a blue grey button that when pressed, turns green and then when pressed again turns back to blue grey. I now need that same button to also tick up an integer when pressed and then to tick down the integer when pressed again.
here is the code:
class _MainPageState extends State<MainPage> {
int secondaryLeftCounter = 0; //integer to change
bool so1HasBeenPressed01 = false;
#override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(50.0),
child: InkWell(
onTap: () {
setState(() {
so1HasBeenPressed01 = !so1HasBeenPressed01;
});
},
child: Container(
width: 30.0,
height: 30.0,
color: so1HasBeenPressed01
? Colors.green
: Colors.blueGrey[900],
),
),
),],);
I can make it work if there are two buttons (one for ticking up and one for ticking down) but am struggling to get it to work with everything happening with the same button.
cheers
Use this code:
onTap: () {
setState(() {
so1HasBeenPressed01 = !so1HasBeenPressed01;
if(so1HasBeenPressed01)
secondaryLeftCounter++;
else
secondaryLeftCounter--;
});
},
Related
I'm trying to make buttons that turn grey after having been pressed. I read up on how to do this. The best way I could find is to set the material color with a ternary operator and then change the condition for that in a setState(() {}) block:
Container vehicleButton(IconData icon_, String text_, {required Function onClickAction}){
const double buttonSizeX = 200;
const double buttonSizeY = 100;
const double iconSize = 60;
const double buttonTextSize = 15;
const double buttonMargin = 5;
Color buttonColor = const Color(0xff2196f3);
const Color iconColor = Color(0xffffffff);
const Color buttonTextColor = Color(0xffffffff);
bool pressed = false;
return Container(padding: const EdgeInsets.only(left: buttonMargin, right: buttonMargin, top: buttonMargin, bottom: buttonMargin), child: SizedBox.fromSize(
size: Size(buttonSizeX, buttonSizeY), child: Material(color: pressed ? Color.fromARGB(255, 143, 143, 143) : buttonColor, child: InkWell(
onTap: () {
setState(() {
pressed = true;
});
onClickAction();
},
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
Icon(icon_, color: iconColor, size: iconSize),
Text(text_, style: TextStyle(fontSize: buttonTextSize, color: buttonTextColor)),
])))));
}
However, I'm getting a warning that the code after the ? in my ternary operator is dead code. And indeed, the button does not turn grey after pressing.
I thought maybe the values of Material are final and cannot be changed, but this wouldn't explain why all the examples I could find on the internet use this method.
You have:
Container vehicleButton(...) {
bool pressed = false;
return Container(
...
child: SizedBox.fromSize(
...
child: Material(
color: pressed ? Color.fromARGB(255, 143, 143, 143) : buttonColor,
child: InkWell(
onTap: () {
setState(() {
pressed = true;
});
onClickAction();
},
The Dart analysis tools are correctly reporting that that Color.fromARGB(...) is dead code because the conditional ternary operator checks the state of the local pressed variable, which at the time it's checked, is always false. Although the onTap handler sets pressed = true, it's setting the state of the local pressed variable, which will never be read again.
You likely intend for pressed to be a member variable of whatever State class contains the vehicleButton method.
Instead of using a SizedBox I suggest you to use the buttons provided by flutter dev: https://docs.flutter.dev/release/breaking-changes/buttons
A simple try you can give is:
RaisedButton(
child: new Text('Attention'),
textColor: Colors.white,
color: pressColor ? Colors.grey : Colors.blue, //Choose your personal colors
onPressed: () => setState(() => pressColor = !pressColor), //change the button colors
);
I was trying to make a form that shows one field at the time that acomplishes the next things:
When pressing a "next" button, it validates the field and let the user go to the next field if everything is ok.
When the user presses the next button in the keyboard it should do the same.
If possible, a sliding animation between fields.
What i came up with was something like this:
List<Widget> questions = [List of textFieldForm]
int pageCount = 0;
GlobalKey _formKey = GlobalKey<FormState>();
pickSection(pageCount) {
return questions[pageCount];
}
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: [
pickSection(widget.pageCount),
Container(
child: Row(children: [
Container(
width: screenWidth * 0.4,
child: TextButton(
onPressed: widget.pageCount == 0
? null
: () {
setState(() {
widget.pageCount--;
}),
child: Text("BACK"),
),
),
Container(
width: screenWidth * 0.4,
child: TextButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
if (widget.pageCount == questions.length - 1) {
print("FORM ENDS");
} else {
setState(() {
widget.pageCount++;
});
}
}
},
child: Text("NEXT"),
),
),
])
),
]),
),
}
This way i validate every field when it's index is called since i treat every widget as it's own form, but i couldn't think of a way to implement an animation, or make the field advance using the next button on the keyboard(again, because this treats every field as it's own form).
Please help me figure out how to implement this. Animation is not important but using the next button to advance fields is crucial.
Thanks in advance.
You can achieve this using Visibility widget(which is used to show a widget on condition) and maintaining flags.
bool goToNextField = false;
TextButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
goToNextField = true;
if (widget.pageCount == questions.length - 1) {
print("FORM ENDS");
} else {
setState(() {
widget.pageCount++;
});
}
}
},
And in the next widget use a Visibility widget
Widget nextField () {
return Visibility(
visible: goToNextField,
child :
// what you want to show when next button is pressed
);
}
I have a dialog box which is a stateful widget with multiple tabs wrapped inside Animated Switcher.
Inside it I have a button which on clicked calls a function switchPage() which has a switch statement with each case setting the state of Widget? currentTab variable to a different one.
The problem here arrives when I use this switchPage() function to change the value of currentTab to a different widget also wrapped in a different method getWidget2()
The code for the
Example on DartPad
Try clicking as I suggest...
Click Floating Button.
Click on the first checkbox.
Now click on PAGE 2 button.
Click the second checkbox only once. Now notice the checkbox doesn't work when clicked.
Click PAGE 1 again to go the working checkbox.
Now click on PAGE 2 button again. The Checkbox value and state did change but did not update the time it was clicked, but it has updated when we forcefully re visited the checkbox.
I cannot find solution to this anywhere and I really need the code structure to be as optimized as possible.
Please, if anyone has any explanation or any suggestions, it would be greatly appreciated..
Thanks, in advance.
This is a very rough working example, but you can build upon it.
In the code below, you can see that I have created two methods that handle setting the state of the checkbox for each widget. I have also reset the page once this method is triggered. What this does, is trigger the redrawing of the inner widgets (which is what I explained in my comment).
class _DemoDialogState extends State<DemoDialog> {
Widget? currentTab;
bool valueOfCheckbox1 = false;
bool valueOfCheckbox2 = false;
void switchPage(name) {
switch (name) {
case 1:
setState(() {
currentTab = getWidget1(setCheckbox1State); // <---- Notice the change here
});
break;
case 2:
setState(() {
currentTab = getWidget2(setCheckbox2State); // <---- Notice the change here
});
break;
}
}
void setCheckbox1State(bool? newState) {
if (newState != null) {
setState(() { // <---- Notice the change here
valueOfCheckbox1 = newState;
currentTab = getWidget1(setCheckbox1State);
});
}
}
void setCheckbox2State(bool? newState) {
if (newState != null) {
setState(() { // <---- Notice the change here
valueOfCheckbox2 = newState;
currentTab = getWidget2(setCheckbox2State);
});
}
}
Widget getWidget1(Function(bool?) checkboxFunction) {
return Container(
child: Row(
children: [
Text('Hello from widget 1'),
Checkbox(
value: valueOfCheckbox1,
onChanged: (value) { // <---- Notice the change here
checkboxFunction(value);
})
],
));
}
Widget getWidget2(Function(bool?) checkboxFunction) {
return Container(
child: Row(
children: [
Text('Hello from widget 2'),
Checkbox(
value: valueOfCheckbox2,
onChanged: (value) { // <---- Notice the change here
checkboxFunction(value);
})
],
));
}
#override
Widget build(BuildContext context) {
return Dialog(
child: Container(
width: 280,
height: 600,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
AnimatedSwitcher(
duration: Duration(milliseconds: 250),
reverseDuration: Duration(milliseconds: 250),
transitionBuilder: (child, animation) {
var begin = Offset(0.5, 0);
var end = Offset.zero;
var curve = Curves.easeIn;
var tween = Tween(begin: begin, end: end)
.chain(CurveTween(curve: curve));
var begin2 = 0.0;
var end2 = 1.0;
var curve2 = Curves.easeIn;
var tween2 = Tween(begin: begin2, end: end2)
.chain(CurveTween(curve: curve2));
return SlideTransition(
position: animation.drive(tween),
child: FadeTransition(
opacity: animation.drive(tween2), child: child),
);
},
layoutBuilder: (widget, list) {
return Align(
alignment: Alignment.topCenter,
child: widget,
);
}, // <---- Notice the change here
child: currentTab == null ? getWidget1(setCheckbox1State) : currentTab,
),
TextButton(
onPressed: () {
switchPage(1);
},
child: Text('PAGE 1')),
TextButton(
onPressed: () {
switchPage(2);
},
child: Text('PAGE 2'))
],
),
),
);
}
}
This is just an example that makes things work, but it in no way represents how you should build things appropriately. I would look into separating the code into stateless and stateful widgets.
I am trying to build a whatsapp clone and when I was working on the changing the camera from front and back. I was trying to change the Icon in the Icon button but it was not changing
I will attach my code file below
Widget bottomIcon({Icon icon,double size,Function onpress}){
return IconButton(
icon: icon,
iconSize: size,
color: Colors.white,
onPressed: onpress,
);
}
Icon iconForcam=Icon(Icons.camera_rear);
#override
Widget build(BuildContext context) {
if (!controller.value.isInitialized) {
return Container();
}
return MaterialApp(
home: Padding(
padding: const EdgeInsets.all(1.0),
child: Stack(
fit: StackFit.expand,
children: [
CameraPreview(controller),
Positioned(
bottom: 0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
SizedBox(width: 20.0,),
bottomIcon(icon: Icon(Icons.flash_on_rounded),size: 50.0),
SizedBox(width: 20.0,),
bottomIcon(icon: Icon(Icons.fiber_manual_record_outlined),size: 100.0),
SizedBox(width: 30.0,),
bottomIcon(icon: iconForcam,size: 50.0,onpress: (){
setState(() {
if(iconForcam == Icon(Icons.camera_front)){
iconForcam = Icon(Icons.camera_rear);
}else if(iconForcam == Icon(Icons.camera_rear)){
print('rearcam');
iconForcam = Icon(Icons.camera_front);
}
});
//toggleCamera();
}),
],
),
),
],
),
),
);
}
}
I have the doubt that in the if I can comapre two icons in the if Statement.
You can define a boolean variable
//Define
bool _isFront = true;
//Usage
bottomIcon(
icon: _isFront ?
Icons.camera_front : Icons.camera_rear,
size: 50.0, onpress: (){
setState(() {
_isFront = !_isFront;
});
//toggleCamera();
})
I tried like this and got that correct
//Defint
int _oldIndex=0;
Icon iconForcam=Icon(Icons.camera_rear);
//Inside code
bottomIcon(icon: iconForcam,size: 50.0,onpress: (){
setState(() {
if(_oldIndex == 0){
iconForcam = Icon(Icons.camera_rear);
_oldIndex = 1;
}else if(_oldIndex == 1){
//print('rearcam');
iconForcam = Icon(Icons.camera_front);
_oldIndex = 0;
}
});
toggleCamera(_oldIndex);
}),
You can store whether the front camera is on or not in shared_prefernces or database, use provider/stream/bloc to expose this value to UI. Now you can use this package to change icon with animation. Install this package to your flutter project, import it in the file, and then replace icon property of the camera button with the below code:
AdvancedIcon(
icon: Icons.camera_front,
secondaryIcon: Icons.camera_rear,
state: isFrontCameraOn ? AdvancedIconState.primary : AdvancedIconState.secondary,
)
Now the icon will automatically change depending on whether the front camera is on or not.
If you have problem with the database or provider part of this question just let me know.
I'm trying to create a simple vertical scrolling calendar.
Problem is that I can't manage to find a way to reset back to previous state in case I tap on a new container.
Here's the code:
class CalendarBox extends StatelessWidget {
BoxProprieties boxProprieties = BoxProprieties();
Map item;
CalendarBox({this.item});
bool selected = false;
#override
Widget build(BuildContext context) {
return Consumer<Producer>(
builder: (context, producer, child) => GestureDetector(
onTap: () {
print(item['dateTime']);
selected = producer.selectedState(selected);
},
child: AnimatedContainer(
duration: Duration(milliseconds: 100),
color: selected == true ? Colors.blue : Colors.grey[200],
height: 80,
width: 50,
margin: EdgeInsets.only(top: 5),
child: Column(
children: [
Text(
'${item['dayNum']}',
style: TextStyle(
fontWeight: FontWeight.bold,
color: boxProprieties.dayColor(item['dateTime'])),
),
],
),
),
),
);
}
}
Here's the situation:
One way to achieve it is, create a model for boxes and keep a value current selected block, in your model you will have the index assigned to that block,
int currentSelected =1; //initial value
class Block{
int id;
..
.. // any other stuff
}
now in your code, the check modifies to
block.id == currentSelected ? Colors.blue : Colors.grey[200],
your on tap modifies to
onTap: () {
setState(){
currentSelected = block.id
};
},
If you want to prevent the rebuild of the whole thing every time you can use valueNotifire for current selected block. Hope this gives you an idea.