I just can't figure out what is the problem with this set state method in flutter. Everything seems okay. But the text is not updating on onPressed.
class NetBalanceWidget extends StatefulWidget {
#override
_NetBalanceWidgetState createState() => _NetBalanceWidgetState();
}
class _NetBalanceWidgetState extends State<NetBalanceWidget> {
#override
Widget build(BuildContext context) {
String text = 'NetBalance-Amount';
return RawMaterialButton(
onPressed: () {
setState(() {
text = 'It works';
});
},
child: Container(
height: 80.0,
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(text),
Text('0.00'),
],
),
),
),
);
}
}
You have text as a local variable in the build method. setState is essentially just calling build again, and is resetting the value of text back to its default of 'NetBalance-Amount'.
Move its declaration outside of build:
class _NetBalanceWidgetState extends State<NetBalanceWidget> {
String text = 'NetBalance-Amount';
#override
Widget build(BuildContext context) {
return RawMaterialButton(
onPressed: () {
setState(() {
text = 'It works';
});
},
child: Container(
height: 80.0,
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(text),
Text('0.00'),
],
),
),
),
);
}
}
Related
I have an IconButton and in the onPressed() method I want to call a void method that receives an incremental number as a parameter when the Button is clicked, then when obtaining this value it must call another void which calculates the days of weeks.
I have tested the function and if I put the values in hard it does work, however when I put it in the widget it always returns the same value and does not change, no matter how much I put the setState method, I don't know how to increase said value.
Here I attach part of the code:
import 'package:intl/intl.dart';
import 'package:flutter/material.dart';
class ExampleScreen extends StatefulWidget {
final String? text1;
final String? text2;
final String? text3;
const ExampleScreen({Key? key,
this.text1,
this.text2,
this.text3}
) : super(key: key);
#override
State<ExampleScreen> createState() => _ExampleScreenState();
}
class _ExampleScreenState extends State<ExampleScreen> {
int counter = 1;
void increase(){
counter++;
setState(() {
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: const EdgeInsets.fromLTRB(10,0,0,0),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
_calendar(widget.text1,widget.text2,widget.text3,counter)
],
),
//),
),
)
);
}
}
_calendar(text1,text2,text3, int counter) => Container(
width: 250,
height: 50,
margin: const EdgeInsets.fromLTRB(50,0,0,0),
alignment: Alignment.center,
child: Wrap(
children:[
Container(
height: 225,
width: 225,
child: Column(
children: [
const SizedBox(height: 10,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
IconButton(
onPressed: () {
//When I call the function increase it tells me that the function is not declared
calculation_days(counter);
print('amount : $counter');
},
icon:const Icon(Icons.arrow_back_ios_new_outlined,size: 10)
),
const Text('Title',style: TextStyle(fontSize: 12)),
IconButton(
onPressed: () {},
icon:const Icon(Icons.arrow_forward_ios_outlined,size: 10)
),
],
),
]
),
),
]
)
);
void calculation_days(int week)
{
int firstday;
List<String> days;
List<String> daysxWeek;
days=findPreviousSaturdays1(count: week);
firstday= int.parse(days[week-1]);
daysxWeek=[firstday.toString()];
daysxWeek.add(firstday.toString());
}
since you declare it inside the StatefulWidget, not the State, you need to access it inside your onPressed method like this:
widget.increase()
IconButton(
onPressed: () {
widget.increase(); // call it like this.
},
icon:const Icon(Icons.arrow_back_ios_new_outlined,size: 10)
);
Another solution is that you can move your increase() from StatefulWidget to the State class, then you can use it by calling increase() instead of widget.increase().
I want to make TextFormField enabled by press a button which is not in the same level,how to pass the value from the button?
return Scaffold(
child:Column(
children:[
Container(
child: Row(
children[
Textbutton(),
.......//otherButtons
]
)
),
DefaultTabController(
child: Column(
children[
TabBar(),
TabBarView(
child:Column(
children[
TextFormField(),
.......//otherTextFormFields
]
)
)
]
)
)
]
)
);
You can set text through TextEditingController. and to disable user input, use readOnly:true. You can test the widget and get the concept how it works.
class ColorTest extends StatefulWidget {
ColorTest({Key? key}) : super(key: key);
#override
State<ColorTest> createState() => _ColorTestState();
}
class _ColorTestState extends State<ColorTest> {
TextEditingController controller = TextEditingController();
bool readOnly = true;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: [
TextButton(
onPressed: () {
controller.text = "Got the text from button click";
setState(() {});
},
child: Text("set text"),
),
TextFormField(
controller: controller,
readOnly: readOnly,
),
TextButton(
onPressed: () {
readOnly = !readOnly;
setState(() {});
},
child: Text("ReadOnlyMode: $readOnly"),
),
],
)
// materialButto(),
),
);
}
}
I want to show SizeBox widget by random. when I open this class it should be random to show Size Box 1 first or Size Box 2 first.
class Page extends StatelessWidget {
var random = new Random();
int randomNumber;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Flexible(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
randomNumber = random.nextInt(1);
if(randomNumber == 1){
/////////////////////////////////////// Size box 1 ////////////////////////////////////
SizedBox(
child: TextButton(
onPressed: () {
AlertDialog(
title: Text('a'),
content: Text('a'));
},
child: Image.asset('images/test.jpg'),
)),
}else{
/////////////////////////////////////// Size box 2 ////////////////////////////////////
SizedBox(
child: TextButton(
onPressed: () {
AlertDialog(
title: Text('b'),
content: Text('b'));
},
child: Image.asset('images/test2.jpg'),
)),
}
I try to use randomNumber = random.nextInt(1) in children: <Widget>[] but it show
The element type 'int' can't be assigned to the list type 'Widget'.dart(list_element_type_not_assignable)
It seems I cannot write dart code in widget. Can I random to show SizeBox widget ?
The error occurs because you called randomNumber = random.nextInt(1); inside the Row children. Since randomNumber is of type int and not of type Widget you can't do this. One way to fix this is to create a StatefulWidget and set the randomNumber in initState method.
By the way using if/else inside children of Row/Column you don't put the curly brackets {}.
import 'package:flutter/material.dart';
import 'dart:math';
class Page extends StatefulWidget {
#override
_Page createState() => _Page();
}
class _Page extends State<Page> {
var random = new Random();
int randomNumber;
#override
void initState(){
randomNumber = random.nextInt(1);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Flexible(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
if (randomNumber == 1)
/////////////////////////////////////// Size box 1 ////////////////////////////////////
SizedBox(
child: TextButton(
onPressed: () {
AlertDialog(title: Text('a'), content: Text('a'));
},
child: Image.asset('images/test.jpg'),
),
)
else
/////////////////////////////////////// Size box 2 ////////////////////////////////////
SizedBox(
child: TextButton(
onPressed: () {
AlertDialog(title: Text('b'), content: Text('b'));
},
child: Image.asset('images/test2.jpg'),
),
),
],
),
),
],
),
),
);
}
}
I am using the package
country_code_picker: ^1.4.0
https://pub.dev/packages/country_code_picker#-installing-tab-
with flutter 1.17.3
Which is pretty much one of the only country code picker packages. But I have one serious problem an I don't have a clue what it could be.
When I run this code
import 'package:flutter/material.dart';
import 'package:country_code_picker/country_code_picker.dart';
void main() {
runApp(App());
}
class App extends StatelessWidget {
App();
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: TestWidget(),
);
}
}
class TestWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(body: _buildCountryPicker(context));
}
Widget _buildCountryPicker(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Center(
child: CountryCodePicker(
initialSelection: 'NL',
),
),
);
}
}
And I open the dialog to select a country. I scroll in the list and then select the TextField my keyboard opens and when I try to type something my entire app freezes. I can't even hot reload. I don't get a single error.
I am running this on my Huawei P30, but I also experience this on other android devices. I don't know if this is a flutter bug or a country code picker bug.
I think it is probably in this widget somewhere. If anyone could point me in the right direction it would help me alot!
class SelectionDialog extends StatefulWidget {
final List<CountryCode> elements;
final bool showCountryOnly;
final InputDecoration searchDecoration;
final TextStyle searchStyle;
final TextStyle textStyle;
final WidgetBuilder emptySearchBuilder;
final bool showFlag;
final double flagWidth;
final Size size;
final bool hideSearch;
/// elements passed as favorite
final List<CountryCode> favoriteElements;
SelectionDialog(
this.elements,
this.favoriteElements, {
Key key,
this.showCountryOnly,
this.emptySearchBuilder,
InputDecoration searchDecoration = const InputDecoration(),
this.searchStyle,
this.textStyle,
this.showFlag,
this.flagWidth = 32,
this.size,
this.hideSearch = false,
}) : assert(searchDecoration != null, 'searchDecoration must not be null!'),
this.searchDecoration =
searchDecoration.copyWith(prefixIcon: Icon(Icons.search)),
super(key: key);
#override
State<StatefulWidget> createState() => _SelectionDialogState();
}
class _SelectionDialogState extends State<SelectionDialog> {
/// this is useful for filtering purpose
List<CountryCode> filteredElements;
#override
Widget build(BuildContext context) => SimpleDialog(
titlePadding: const EdgeInsets.all(0),
title: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
IconButton(
padding: const EdgeInsets.all(0),
iconSize: 20,
icon: Icon(
Icons.close,
),
onPressed: () => Navigator.pop(context),
),
if (!widget.hideSearch)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: TextField(
style: widget.searchStyle,
decoration: widget.searchDecoration,
onChanged: _filterElements,
),
),
],
),
children: [
Container(
width: widget.size?.width ?? MediaQuery.of(context).size.width,
height:
widget.size?.height ?? MediaQuery.of(context).size.height * 0.7,
child: ListView(
children: [
widget.favoriteElements.isEmpty
? const DecoratedBox(decoration: BoxDecoration())
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
...widget.favoriteElements.map(
(f) => SimpleDialogOption(
child: _buildOption(f),
onPressed: () {
_selectItem(f);
},
),
),
const Divider(),
],
),
if (filteredElements.isEmpty)
_buildEmptySearchWidget(context)
else
...filteredElements.map(
(e) => SimpleDialogOption(
key: Key(e.toLongString()),
child: _buildOption(e),
onPressed: () {
_selectItem(e);
},
),
),
],
),
),
],
);
Widget _buildOption(CountryCode e) {
return Container(
width: 400,
child: Flex(
direction: Axis.horizontal,
children: <Widget>[
if (widget.showFlag)
Flexible(
child: Padding(
padding: const EdgeInsets.only(right: 16.0),
child: Image.asset(
e.flagUri,
package: 'country_code_picker',
width: widget.flagWidth,
),
),
),
Expanded(
flex: 4,
child: Text(
widget.showCountryOnly
? e.toCountryStringOnly()
: e.toLongString(),
overflow: TextOverflow.fade,
style: widget.textStyle,
),
),
],
),
);
}
Widget _buildEmptySearchWidget(BuildContext context) {
if (widget.emptySearchBuilder != null) {
return widget.emptySearchBuilder(context);
}
return Center(
child: Text('No country found'),
);
}
#override
void initState() {
filteredElements = widget.elements;
super.initState();
}
void _filterElements(String s) {
s = s.toUpperCase();
setState(() {
filteredElements = widget.elements
.where((e) =>
e.code.contains(s) ||
e.dialCode.contains(s) ||
e.name.toUpperCase().contains(s))
.toList();
});
}
void _selectItem(CountryCode e) {
Navigator.pop(context, e);
}
}
Also filed an issue on the flutter github https://github.com/flutter/flutter/issues/59886
Edit:
I have a video of it right here
https://www.youtube.com/watch?v=669KitFG9ek&feature=youtu.be
I just had to remove the keys, so there probably was a duplicate key
...filteredElements.map(
(e) => SimpleDialogOption(
//key: Key(e.toLongString()),
child: _buildOption(e),
onPressed: () {
_selectItem(e);
},
),
),
I am trying to make a simple image that appears or disappears when a button is pushed. This button resides in a separate class to the image, so in Flutter this creates a massive headache of an issue.
I have read many forums on this and I have tried all the solutions posed but none of them are working for me.
What I am trying to do:
class SinglePlayerMode extends StatefulWidget {
#override
SinglePlayerModeParentState createState() => SinglePlayerModeParentState();
}
class SinglePlayerModeParentState extends State<SinglePlayerMode> {\
bool coinVisible = false;
toggleCoin() {
setState(() {
coinVisible = !coinVisible;
});
}
Widget topMenuRow() {
return Stack(
children: [
Column(
children: [
coinVisible == true ?
Padding(
padding: EdgeInsets.all(50),
child: Container(
height: 60,
width: 60,
color: Colors.blueGrey[0],
decoration: BoxDecoration(
color: Colors.blueAccent,
image: DecorationImage(
image: ExactAssetImage('lib/images/coin_head.jpg'),
fit: BoxFit.cover,
),
),
),
) : Container(
height: 60,
width: 60,
color: Colors.black,
),
],
),
],
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
child: ListView(
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0),
children: [
topMenuRow(),
SizedBox(height: 40),
],
),
),
);
}
And this is the separate class which I would like to trigger the SetState() on coinVisible from:
class dropDownMenu extends StatefulWidget { #override
_dropDownMenuState createState() => _dropDownMenuState();
}
class _dropDownMenuState extends State<dropDownMenu> {
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget> [
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
child: Opacity(
opacity: 0.0,
child: FloatingActionButton(
heroTag: null,
onPressed: (){
//SOMEHOW CALL SetState() ON coinVisble HERE!
},
),
),
);
}
}
But nothing I have tried is working, and I have lost hours.
It simple, you need to send your SinglePlayMode::toggleCoin function as callback to dropDownMenu class.
class dropDownMenu extends StatefulWidget {
final _callback; // callback reference holder
//you will pass the callback here in constructor
dropDownMenu( {#required void toggleCoinCallback() } ) :
_callback = toggleCoinCallback;
#override
_dropDownMenuState createState() => _dropDownMenuState();
}
class _dropDownMenuState extends State<dropDownMenu> {
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget> [
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
child: Opacity(
opacity: 0.0,
child: FloatingActionButton(
heroTag: null,
onPressed: (){
widget?._callback(); // callback calling
},
),
),
);
}
}
Then when you create a dropDownMenu class instance in your SinglePlayerMode class you will do
dropDownMenu(
toggleCoinCallback: toogleCoin,
);