Reputation: 4075
I am new to this Flutter
I am trying to change FlatButton
text while onPressed
. My page design in separate Widget
method, so unable to add setState()
in onPressed
.
I have searched a lot. But, couldn't find. Kindly help me on this.
import 'package:flutter/material.dart';
int number = 10;
class SecondRoute extends StatelessWidget {
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Lists'),
backgroundColor: new Color(0xFF000000),
),
body: DynamicChange(),
);
}
}
class DynamicChange extends StatefulWidget {
@override
StateDynamic createState() => StateDynamic();
} // Class SecondRoute
class StateDynamic extends State<DynamicChange> {
Widget build(BuildContext context) {
return new Scaffold(
body: thisScreenNeeds(),
);
}
}
Widget thisScreenNeeds() {
return Container(
margin: EdgeInsets.only(top: 100, left: 50),
child: FlatButton(
child: Text(
number.toString(),
textAlign: TextAlign.center,
style: (TextStyle(
fontWeight: FontWeight.bold, fontSize: 60, color: Colors.green)),
),
onPressed: () {
// Unable to add, setState(). Throwing error.
},
));
}
Attempt 1
onPressed: () {
// Error: The member 'setState' can only be used within instance members of subclasses
StateDynamic().setState(() {
number = number + 1;
});
},
Attempt 2
class StateDynamic extends State<DynamicChange> {
.....
.........
void _incrementCounter() {
setState(() {
number++;
});
}
.....
.......
}
onPressed: StateDynamic()._incrementCounter,
// Run Time Error:
This happens when you call setState() on a State object for a
widget that hasn't been inserted into the widget tree yet.
It is not necessary to call setState() in the constructor,
since the state is already assumed to be dirty when it is
initially created.
Upvotes: 6
Views: 18944
Reputation: 6876
Keep the method inside State
class. Also better keep the number
variable inside that class too. You can setState
directly only inside the State
class so that's why.
In your case, solution
class SecondRoute extends StatelessWidget {
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Lists'),
backgroundColor: new Color(0xFF000000),
),
body: DynamicChange(),
);
}
}
class DynamicChange extends StatefulWidget {
@override
StateDynamic createState() => StateDynamic();
} // Class SecondRoute
class StateDynamic extends State<DynamicChange> {
int number = 10;
Widget build(BuildContext context) {
return new Scaffold(
body: thisScreenNeeds(),
);
}
Widget thisScreenNeeds() {
return Container(
margin: EdgeInsets.only(top: 100, left: 50),
child: FlatButton(
child: Text(
number.toString(),
textAlign: TextAlign.center,
style: (TextStyle(
fontWeight: FontWeight.bold,
fontSize: 60,
color: Colors.green)),
),
onPressed: () {
setState(() {
number++;
});
},
));
}
}
If you need to seperate widgets completely(as I understand first), you can send VoidCallback
parameter via constructors. Like:
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Home(),
);
}
}
class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
String text = 'Some text';
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(text),
ButtonWidget(stateSetter),
],
),
);
}
void stateSetter() {
setState(() {
text = 'Changed text';
});
}
}
class ButtonWidget extends StatelessWidget {
final VoidCallback stateSetter;
ButtonWidget(this.stateSetter);
@override
Widget build(BuildContext context) {
return RaisedButton(
onPressed: this.stateSetter,
);
}
}
Upvotes: 12