I\'ve the below custom widget that make a Switch
and reads its status (true/false)
Then I add this one to my main app widget (parent), how can I make th
The first possibility is to pass a callback into your child, and the second is to use the of
pattern for your stateful widget. See below.
import 'package:flutter/material.dart';
class MyStatefulWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() => new MyStatefulWidgetState();
static MyStatefulWidgetState of(BuildContext context) {
final MyStatefulWidgetState navigator =
context.ancestorStateOfType(const TypeMatcher<MyStatefulWidgetState>());
assert(() {
if (navigator == null) {
throw new FlutterError(
'MyStatefulWidgetState operation requested with a context that does '
'not include a MyStatefulWidget.');
}
return true;
}());
return navigator;
}
}
class MyStatefulWidgetState extends State<MyStatefulWidget> {
String _string = "Not set yet";
set string(String value) => setState(() => _string = value);
@override
Widget build(BuildContext context) {
return new Column(
children: <Widget>[
new Text(_string),
new MyChildClass(callback: (val) => setState(() => _string = val))
],
);
}
}
typedef void StringCallback(String val);
class MyChildClass extends StatelessWidget {
final StringCallback callback;
MyChildClass({this.callback});
@override
Widget build(BuildContext context) {
return new Column(
children: <Widget>[
new FlatButton(
onPressed: () {
callback("String from method 1");
},
child: new Text("Method 1"),
),
new FlatButton(
onPressed: () {
MyStatefulWidget.of(context).string = "String from method 2";
},
child: new Text("Method 2"),
)
],
);
}
}
void main() => runApp(
new MaterialApp(
builder: (context, child) => new SafeArea(child: new Material(color: Colors.white, child: child)),
home: new MyStatefulWidget(),
),
);
There is also the alternative of using an InheritedWidget instead of a StatefulWidget; this is particularly useful if you want your child widgets to rebuild if the parent widget's data changes and the parent isn't a direct parent. See the inherited widget documentation
Output:
Generally you use Navigator.pop(context, "your data here");
but you can also pass the data in this manner
class ParentScreen extends StatefulWidget {
@override
_ParentScreenState createState() => _ParentScreenState();
}
class _ParentScreenState extends State<ParentScreen> {
String _text = "";
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Parent screen")),
body: Column(
children: <Widget>[
RaisedButton(
child: Text("GO TO CHILD"),
onPressed: () => Navigator.push(context, MaterialPageRoute(builder: (_) => ChildScreen(func: function))),
),
Text(_text),
],
),
);
}
function(value) => setState(() => _text = value);
}
class ChildScreen extends StatelessWidget {
final Function func;
const ChildScreen({Key key, this.func}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Child screen")),
body: RaisedButton(
child: Text("BACK TO PARENT"),
onPressed: () {
func("This is the data which child has passed"); // passing data to parent
Navigator.pop(context);
},
),
);
}
}
In 2020, the function in the highest voted answer is marked deprecated. So here is the modified solution based on that answer:
import 'package:flutter/material.dart';
class MyStatefulWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() => new MyStatefulWidgetState();
// --> NOTE this! <--
static MyStatefulWidgetState of(BuildContext context) =>
context.findAncestorStateOfType<MyStatefulWidgetState>();
}
class MyStatefulWidgetState extends State<MyStatefulWidget> {
String _string = "Not set yet";
set string(String value) => setState(() => _string = value);
@override
Widget build(BuildContext context) {
return new Column(
children: <Widget>[
new Text(_string),
new MyChildClass(callback: (val) => setState(() => _string = val))
],
);
}
}
typedef void StringCallback(String val);
class MyChildClass extends StatelessWidget {
final StringCallback callback;
MyChildClass({this.callback});
@override
Widget build(BuildContext context) {
return new Column(
children: <Widget>[
new FlatButton(
onPressed: () {
callback("String from method 1");
},
child: new Text("Method 1"),
),
new FlatButton(
onPressed: () {
MyStatefulWidget.of(context).string = "String from method 2";
},
child: new Text("Method 2"),
)
],
);
}
}
void main() => runApp(
new MaterialApp(
builder: (context, child) => new SafeArea(child: new Material(color: Colors.white, child: child)),
home: new MyStatefulWidget(),
),
);