如何在Flutter中更新兄弟小部件的状态?
例如,如果我有一个矩形小部件,我可以通过调用setState()
并更改颜色变量来改变小部件内的颜色(如下所示"转动绿色"按钮) 。但是,我想要一个矩形外面的按钮可以改变它的颜色。我如何与Rectangle沟通,知道改变颜色的时间,以及要改变的颜色?
这是我的示例代码。当用户按下"转蓝"按钮,我希望矩形变为蓝色,但我无法从兄弟小部件访问其状态。
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Hello Rectangle',
home: Scaffold(
appBar: AppBar(
title: Text('Hello Rectangle'),
),
body: Column(
children: <Widget>[
HelloRectangle(),
FlatButton(
child: Text('Turn Blue!',
style: TextStyle(fontSize: 40.0),
textAlign: TextAlign.center,
),
onPressed: () {
// How to update state of the Rectangle from here?
},
),
]
),
),
),
);
}
class HelloRectangle extends StatefulWidget {
@override
HelloRectangleState createState() {
return new HelloRectangleState();
}
}
class HelloRectangleState extends State<HelloRectangle> {
Color _color;
@override
void initState() {
super.initState();
_color = Colors.red;
}
@override
Widget build(BuildContext context) {
return Center(
child: Container(
color: _color,
height: 400.0,
width: 300.0,
child: Center(
child: FlatButton(
child: Text('Turn Green!',
style: TextStyle(fontSize: 40.0),
textAlign: TextAlign.center,
),
onPressed: () {
// I can update the state from here because I'm inside the widget
setState(() {
_color = Colors.green;
});
},
),
),
),
);
}
}
答案 0 :(得分:4)
经验法则是您无法访问层次结构中不在您上方的任何窗口小部件的状态。所以,基本上我们需要将状态(颜色)移动到祖先。引入构建Scaffold或Column的StatefulWidget并在其中存储矩形颜色。现在矩形小部件不再需要存储颜色,因此可以成为无状态小部件 - 您可以通过构造函数传递颜色。两个onPressed回调现在都可以调用调用setState的新StatefulWidget上的方法。 (您可以将该方法传递给矩形小部件,以及其他方式。)
答案 1 :(得分:2)
以下是如何从外部进行操作的基本示例。
.
.
.
self.makeLoaderVisible()
let playerItem = AVPlayerItem(url: url)
playerItem.addObserver(self, forKeyPath: "playbackBufferEmpty", options: .new, context: nil)
playerItem.addObserver(self, forKeyPath: "playbackLikelyToKeepUp", options: .new, context: nil)
playerItem.addObserver(self, forKeyPath: "playbackBufferFull", options: .new, context: nil)
avPlayer?.replaceCurrentItem(with: playerItem)
avPlayer?.automaticallyWaitsToMinimizeStalling = false
avPlayer?.playImmediately(atRate: 0)
// avPlayer?.play()
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if object is AVPlayerItem {
switch keyPath! {
case "playbackBufferEmpty":
// Show loader
makeLoaderVisible()
case "playbackLikelyToKeepUp":
// Hide loader
hideLoader()
case "playbackBufferFull":
// Hide loader
hideLoader()
default:
return
}
}
}