Flutter 如何将StatefullWidget中的布尔值从另一个更改为另一个?

Flutter 如何将StatefullWidget中的布尔值从另一个更改为另一个?,flutter,widget,state,setstate,Flutter,Widget,State,Setstate,我是新来的 我试着按一个按钮打开一个面板,然后按面板上的一个按钮关闭它 通过在同一页中编写代码,我成功地做到了这一点 我不能做的是分裂代码,让一切正常工作 我实际上是在初始化为False的小部件状态下调用变量,然后调用if语句:或空容器或我想要的面板 当我按下按钮时,我调用SetState(){},变量变为true以显示面板,然后在面板中有一个做相反事情的按钮 假设我所做的是正确的。如何在新页面中重构面板的情况下继续这样做 我已经了解了一些关于流和继承的小部件的信息,但我还没有完全理解如果您想打

我是新来的

我试着按一个按钮打开一个面板,然后按面板上的一个按钮关闭它

通过在同一页中编写代码,我成功地做到了这一点

我不能做的是分裂代码,让一切正常工作

我实际上是在初始化为False的小部件状态下调用变量,然后调用if语句:或空容器或我想要的面板

当我按下按钮时,我调用SetState(){},变量变为true以显示面板,然后在面板中有一个做相反事情的按钮

假设我所做的是正确的。如何在新页面中重构面板的情况下继续这样做


我已经了解了一些关于流和继承的小部件的信息,但我还没有完全理解

如果您想打开一个对话框(而不是您所谓的“面板”),您只需在再次关闭对话框时返回所选数据即可。
你可以在这里找到一个很好的教程:

如果我理解正确,你想从另一个
StatefullWidget
通知一个
StatefullWidget
。这方面有几种方法,但既然您已经提到了
,我将尝试发布一个示例,并对这种情况进行一些解释

基本上,你可以把小溪看成是一个管道,一端连接到水龙头,另一端则被添加到一个杯子里(端部可以分成多个端部,放在多个杯子中,即“广播流”)。 现在,杯子是监听器(订户),等待水从管道中滴落

水龙头是发射器,当水龙头打开时,它会发出水滴

当另一端放入杯子中时,水龙头可以打开,这是一个带有一些冷传感器的智能水龙头,(当“检测到”订户时,发射器将开始发射事件)

水滴是应用程序中正在发生的实际事件

此外,你还必须记得关闭水龙头,以避免杯子大量泄漏到厨房地板上。(你必须在处理完事件后取消订户,以避免泄漏)

现在,对于您的特殊情况,下面是一段代码片段,可以说明上述比喻:

class ThePannel extends StatefulWidget { // this is the cup
  final Stream<bool> closeMeStream; // this is the pipe 

  const ThePannel({Key key, this.closeMeStream}) : super(key: key);

  @override
  _ThePannelState createState() => _ThePannelState(closeMeStream);
}

class _ThePannelState extends State<ThePannel> {
  bool _closeMe = false;
  final Stream<bool> closeMeStream;
  StreamSubscription _streamSubscription;

  _ThePannelState(this.closeMeStream);

  @override
  void initState() {
    super.initState();
    _streamSubscription = closeMeStream.listen((shouldClose) { // here we listen for new events coming down the pipe
      setState(() {
        _closeMe = shouldClose; // we got a new "droplet" 
      });
    });
  }

  @override
  void dispose() {
    _streamSubscription.cancel(); // THIS IS QUITE IMPORTANT, we have to close the faucet 
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        SomeWidgetHere(shouldClose: _closeMe), 
        RaisedButton(
          onPressed: () {
            setState(() {
              _closeMe = true;
            });
          },
        )
      ],
    );
  }
}

class SomeWidgetThatUseThePreviousOne extends StatefulWidget { // this one is the faucet, it will emit droplets 
  @override
  _SomeWidgetThatUseThePreviousOneState createState() =>
      _SomeWidgetThatUseThePreviousOneState();
}

class _SomeWidgetThatUseThePreviousOneState
    extends State<SomeWidgetThatUseThePreviousOne> {
  final StreamController<bool> thisStreamWillEmitEvents = StreamController(); // this is the end of the pipe linked to the faucet

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        ThePannel(closeMeStream: thisStreamWillEmitEvents.stream), // we send the other end of the pipe to the cup
        RaisedButton(
          child: Text("THIS SHOULD CLOSE THE PANNEL"),
          onPressed: () {
            thisStreamWillEmitEvents.add(true); // we will emit one droplet here
          },
        ),
        RaisedButton(
          child: Text("THIS SHOULD OPEN THE PANNEL"),
          onPressed: () {
            thisStreamWillEmitEvents.add(false); // we will emit another droplet here
          },
        )
      ],
    );
  }

  @override
  void dispose() {
     thisStreamWillEmitEvents.close(); // close the faucet from this end.
     super.dispose();
  }
}
class ThePanel extends StatefulWidget{//这是杯子
最终流closeMeStream;//这是管道
const ThePannel({Key-Key,this.closeMeStream}):super(Key:Key);
@凌驾
_通道状态createState()=>\u通道状态(closeMeStream);
}
类_通道状态扩展状态{
bool\u closeMe=false;
最后一条河流是最近的河流;
StreamSubscription\u StreamSubscription;
_通道状态(这是最接近的流程);
@凌驾
void initState(){
super.initState();
_streamSubscription=closeMeStream.listen((shouldClose){//这里我们监听管道中的新事件
设置状态(){
_closeMe=shouldClose;//我们得到了一个新的“水滴”
});
});
}
@凌驾
无效处置(){
_streamSubscription.cancel();//这很重要,我们必须关闭水龙头
super.dispose();
}
@凌驾
小部件构建(构建上下文){
返回堆栈(
儿童:[
SomeWidgetHere(shouldClose:_closeMe),
升起的按钮(
已按下:(){
设置状态(){
_closeMe=true;
});
},
)
],
);
}
}
类somewidget使用前一个扩展状态窗口小部件{//这是水龙头,它将发出水滴
@凌驾
_使用前一个状态createState()的某些Widget=>
_某些人使用前一个状态();
}
类_somewidget使用前一个状态
扩展状态{
最终StreamController thisStreamWillEmitEvents=StreamController();//这是链接到水龙头的管道的末端
@凌驾
小部件构建(构建上下文){
返回堆栈(
儿童:[
管道(closeMeStream:thistreamwillemitevents.stream),//我们将管道的另一端发送到杯子
升起的按钮(
子项:文本(“这应该关闭窗格”),
已按下:(){
thisStreamWillEmitEvents.add(true);//我们将在此处发射一个液滴
},
),
升起的按钮(
子项:文本(“这将打开窗格”),
已按下:(){
thisStreamWillEmitEvents.add(false);//我们将在此处发射另一个液滴
},
)
],
);
}
@凌驾
无效处置(){
thisStreamWillEmitEvents.close();//从此端关闭水龙头。
super.dispose();
}
}

我希望我的类比能帮助您稍微了解一下streams的概念。

您可以从另一个屏幕导航并返回数据,如下所示:

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    title: 'Returning Data',
    home: HomeScreen(),
  ));
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Returning Data Demo'),
      ),
      body: Center(child: SelectionButton()),
    );
  }
}

class SelectionButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      onPressed: () {
        _navigateAndDisplaySelection(context);
      },
      child: Text('Pick an option, any option!'),
    );
  }

  // A method that launches the SelectionScreen and awaits the result from
  // Navigator.pop!
  _navigateAndDisplaySelection(BuildContext context) async {
    // Navigator.push returns a Future that will complete after we call
    // Navigator.pop on the Selection Screen!
    final result = await Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => SelectionScreen()),
    );

    // After the Selection Screen returns a result, hide any previous snackbars
    // and show the new result!
    Scaffold.of(context)
      ..removeCurrentSnackBar()
      ..showSnackBar(SnackBar(content: Text("$result")));
  }
}

class SelectionScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Pick an option'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: RaisedButton(
                onPressed: () {
                  // Close the screen and return "Yep!" as the result
                  Navigator.pop(context, 'Yep!');
                },
                child: Text('Yep!'),
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: RaisedButton(
                onPressed: () {
                  // Close the screen and return "Nope!" as the result
                  Navigator.pop(context, 'Nope.');
                },
                child: Text('Nope.'),
              ),
            )
          ],
        ),
      ),
    );
  }
}
导入“包装:颤振/材料.省道”;
void main(){
runApp(材料应用程序)(
标题:“返回数据”,
主页:主屏幕(),
));
}
类主屏幕扩展无状态小部件{
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(
标题:文本(“返回数据演示”),
),
主体:居中(子项:SelectionButton()),
);
}
}
类SelectionButton扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回上升按钮(
已按下:(){
_导航显示选择(上下文);
},
子项:文本('选择一个选项,任意选项!'),
);
}
//启动SelectionScreen并等待来自的结果的方法
//Navigator.pop!
_navigateAndDisplaySelection(BuildContext上下文)异步{
//Navigator.push返回一个在调用
//选择屏幕上的Navigator.pop!
最终结果=等待Navigator.push(
上下文
MaterialPage路由(生成器:(上下文)=>SelectionScreen()),
);
//在选择屏幕返回结果后,隐藏任何p