我有以下自定义小部件,它可以创建Switch并读取其状态(true/false)
然后我将这个添加到我的主应用程序小部件(父级),如何让父级知道交换机的值!
import 'package:flutter/material.dart';
class Switchy extends StatefulWidget{
Switchy({Key key}) : super(key: key);
@override
State<StatefulWidget> createState() => new _SwitchyState();
}
class _SwitchyState extends State<Switchy> {
var myvalue = true;
void onchange(bool value) {
setState(() {
this.myvalue = value; // I need the parent to receive this one!
print('value is: $value');
});
}
@override
Widget build(BuildContext context) {
return
new Card(
child: new Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new Text("Enable/Disable the app in the background",
textAlign: TextAlign.left,
textDirection: TextDirection.ltr,),
new Switch(value: myvalue, onChanged: (bool value) => onchange(value)),
],
),
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
在main.dart(父)文件中,我从这开始:
import 'widgets.dart';
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.deepOrange,
),
home: new MyHomePage(title: 'My App settup'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Widget e = new Switchy();
//...
}
Run Code Online (Sandbox Code Playgroud)
rmt*_*zie 25
第一种可能性是将回调传递给您的孩子,第二种可能是将of模式用于您的有状态小部件.见下文.
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(),
),
);
Run Code Online (Sandbox Code Playgroud)
还有使用InheritedWidget而不是StatefulWidget的替代方法; 如果您希望子窗口小部件重建,如果父窗口小部件的数据发生更改且父窗口不是直接父窗口,则此功能特别有用.请参阅继承的小部件文档
Mar*_*cin 20
我认为通知是一个相当文明的解决方案,它们允许非常干净的通信,而无需变量杂耍,并且如果您需要它们,它们就会冒泡:
定义通知:
class SwitchChanged extends Notification {
final bool val
SwitchChanged(this.val);
}
Run Code Online (Sandbox Code Playgroud)
在您孩子的事件处理程序中发出通知:
onPressed: () {
SwitchChanged(true).dispatch(context);
}
Run Code Online (Sandbox Code Playgroud)
最后,用通知监听器包装你的父级:
NotificationListener<SwitchChanged>(
child: YourParent(...),
onNotification: (n) {
setState(() {
// Trigger action on parent via setState or do whatever you like.
});
return true;
}
)
Run Code Online (Sandbox Code Playgroud)
Cop*_*oad 12
您可以将父窗口小部件中定义的回调传递给子窗口小部件,一旦在子窗口小部件中执行操作,就会调用回调。
class ParentWidget extends StatelessWidget {
// This gets called when the button is pressed in the ChildWidget.
void _onData(String data) {
print(data); // Hello World
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: ChildWidget(onData: _onData),
);
}
}
class ChildWidget extends StatelessWidget {
final void Function(String) onData;
ChildWidget({
super.key,
required this.onData,
});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () {
// Pass 'Hello World' to parent widget.
onData('Hello World');
},
child: Text('Button'),
);
}
}
Run Code Online (Sandbox Code Playgroud)
2020 年,投票最高的答案中的函数被标记为已弃用。所以这是基于该答案的修改后的解决方案。
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(),
),
);
Run Code Online (Sandbox Code Playgroud)
但是,这个问题的答案中提到的方法有一个缺点。从文档:
但是,一般而言,请考虑使用触发祖先状态更改的回调,而不是使用此方法隐含的命令式样式。这通常会导致更易于维护和可重用的代码,因为它使小部件彼此分离。
调用此方法的开销相对较大(树的深度为 O(N))。仅当从该小部件到所需祖先的距离已知很小且有界时才调用此方法。
| 归档时间: |
|
| 查看次数: |
11538 次 |
| 最近记录: |