Reputation: 22437
This is my widget tree. I want to change the Text widget in the MemberSection
class when I press RaisedButton
in the AdminSection
class. Both MemberSection
and AdminSection
are in HomePage
class.
Below are dart files:
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
home: HomePage(),
),
);
}
class HomePage extends StatelessWidget {
final int count = 0;
@override
Widget build(BuildContext context) {
return new Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[MemberSection(count), AdminSection(count)],
),
);
}
}
class MemberSection extends StatefulWidget {
MemberSection(this.count);
final int count;
@override
_MemberSectionState createState() => new _MemberSectionState();
}
class _MemberSectionState extends State<MemberSection> {
@override
Widget build(BuildContext context) {
return new Text('${widget.count} member(s)');//I need to change this widget
}
}
class AdminSection extends StatefulWidget {
AdminSection(this.count);
final int count;
@override
_AdminSectionState createState() => new _AdminSectionState();
}
class _AdminSectionState extends State<AdminSection> {
void incrementer() {
setState(() {
//widget.count++; //cannt do
});
}
void decrementer() {
setState(() {
//widget.count--; //cannt do
});
}
@override
Widget build(BuildContext context) {
return new Column(
children: <Widget>[
Text('${widget.count} admin(s)'),//Also, I need to change this widget
ButtonBar(
children: <Widget>[
RaisedButton(
child: Text('add a member'),
onPressed: incrementer,
),
RaisedButton(
child: Text('delete a member'),
onPressed: decrementer,
),
],
),
],
);
}
}
Note: this example for to demonstrate my problem.
I know that I can implement incrementer
and decrementer
in HomePage
class and pass the function down the widget but according to this scenario it cannot be done, because one RaisedButton
widgets are in other side of the widget tree.
Update:
Linked duplicate question is different from my question because, I'm not instantiating the MemberSection
inside AdminSection
Upvotes: 0
Views: 3874
Reputation: 22437
Yes, it is possible.
The easiest way is to use InheritedWidget
You may have remember a method of(context)
, as examples:
MediaQuery.of(context).size
Navigator.of(context).pop()
Theme.of(context).canvasColor
Those are inherited widgets.You are using of()
anywhere in your app, you can access your theme, because they're inherited. Using of
method you can change the state of your widget tree after you implement your widget tree.
So, your example code should look like below:
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
home: MyApp(),
),
);
}
//this is a newly added stateful widget to use inherited widget
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int count = 0;
void incrementer() {
setState(() {
count++;
});
}
void decrementer() {
setState(() {
count--;
});
}
@override
Widget build(BuildContext context) {
return CounterState(
count: count,
incrementer: incrementer,
decrementer: decrementer,
child: HomePage(),
);
}
}
//this is the inherited widget
class CounterState extends InheritedWidget {
CounterState({Key key, this.count, this.incrementer, this.decrementer, Widget child})
: super(key: key, child: child);
final int count;
final Function incrementer;
final Function decrementer;
@override
bool updateShouldNotify(CounterState oldWidget) {
return count != oldWidget.count;
}
static of(BuildContext context) {
return context.inheritFromWidgetOfExactType(CounterState);
}
}
//make below classes stateless(not must but useless)
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
MemberSection(),
AdminSection()
],
),
);
}
}
class MemberSection extends StatelessWidget {
@override
Widget build(BuildContext context) {
final counterState = CounterState.of(context);
return new Text('${counterState.count} member(s)');
}
}
class AdminSection extends StatelessWidget {
@override
Widget build(BuildContext context) {
final counterState = CounterState.of(context);
return new Column(
children: <Widget>[
Text('${counterState.count} admin(s)'),
ButtonBar(
children: <Widget>[
RaisedButton(child: Text('add a member'), onPressed: counterState.incrementer,),
RaisedButton(child: Text('delete a member'), onPressed: counterState.decrementer,),
],
),
],
);
}
}
One great tutorial can be found here.
Upvotes: 2