当弹出时强制Flutter导航器重新加载状态

12 浏览
0 Comments

当弹出时强制Flutter导航器重新加载状态

我在Flutter中有一个带有按钮的StatefulWidget,使用Navigator.push()将我导航到另一个StatefulWidget。在第二个小部件中,我更改了全局状态(一些用户首选项)。当我使用Navigator.pop()从第二个小部件返回到第一个小部件时,第一个小部件处于旧状态,但我希望强制重新加载它。有什么想法如何实现这一点?我有一个想法,但它看起来很丑陋:

  1. 弹出以删除第二个小部件(当前小部件)
  2. 再次弹出以删除第一个小部件(上一个小部件)
  3. 推送第一个小部件(它应该强制重绘)
admin 更改状态以发布 2023年5月20日
0
0 Comments

简短回答:

在第一页使用此代码:

Navigator.pushNamed(context, '/page2').then((_) => setState(() {}));

在第二页使用此代码:

Navigator.pop(context);


有2件事,传递数据从

  • 第一页到第二页

    在第一页使用此代码

      // sending "Foo" from 1st
      Navigator.push(context, MaterialPageRoute(builder: (_) => Page2("Foo")));
    

    在第二页使用此代码。

      class Page2 extends StatelessWidget {
        final String string;
        Page2(this.string); // receiving "Foo" in 2nd
        ...
      }
    


  • 第二页到第一页

    在第二页使用此代码

      // sending "Bar" from 2nd
      Navigator.pop(context, "Bar");
    

    在第一页使用此代码,它与先前使用的相同,但稍有修改。

      // receiving "Bar" in 1st
      String received = await Navigator.push(context, MaterialPageRoute(builder: (_) => Page2("Foo")));
    

0
0 Comments

这里有几件事情你可以做。@Mahi的回答是正确的,但可以更简洁,实际上使用push而不是showDialog,因为OP正在询问这个。这是一个使用Navigator.push的示例:

import 'package:flutter/material.dart';
class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.green,
      child: Column(
        children: [
          RaisedButton(
            onPressed: () => Navigator.pop(context),
            child: Text('back'),
          ),
        ],
      ),
    );
  }
}
class FirstPage extends StatefulWidget {
  @override
  State createState() => new FirstPageState();
}
class FirstPageState extends State {
  Color color = Colors.white;
  @override
  Widget build(BuildContext context) {
    return new Container(
      color: color,
      child: Column(
        children: [
          RaisedButton(
            child: Text("next"),
            onPressed: () async {
              final value = await Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => SecondPage()),
                ),
              );
              setState(() {
                color = color == Colors.white ? Colors.grey : Colors.white;
              });
            },
          ),
        ],
      ),
    );
  }
}
void main() => runApp(
      MaterialApp(
        builder: (context, child) => SafeArea(child: child),
        home: FirstPage(),
      ),
    );

但是,还有另一种方法可以做到这一点,可能更适合您的用例。如果您将global用作影响第一页构建的内容,则可以使用InheritedWidget来定义全局用户首选项,并且每次更改时,您的FirstPage将重新构建。即使在无状态小部件中也适用,如下所示(但也应适用于有状态小部件)。

Flutter中InheritedWidget的一个示例是应用程序的Theme,虽然他们在小部件中定义它,而不是像我这里直接构建。

import 'package:flutter/material.dart';
import 'package:meta/meta.dart';
class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.green,
      child: Column(
        children: [
          RaisedButton(
            onPressed: () {
              ColorDefinition.of(context).toggleColor();
              Navigator.pop(context);
            },
            child: new Text("back"),
          ),
        ],
      ),
    );
  }
}
class ColorDefinition extends InheritedWidget {
  ColorDefinition({
    Key key,
    @required Widget child,
  }): super(key: key, child: child);
  Color color = Colors.white;
  static ColorDefinition of(BuildContext context) {
    return context.inheritFromWidgetOfExactType(ColorDefinition);
  }
  void toggleColor() {
    color = color == Colors.white ? Colors.grey : Colors.white;
    print("color set to $color");
  }
  @override
  bool updateShouldNotify(ColorDefinition oldWidget) =>
      color != oldWidget.color;
}
class FirstPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var color = ColorDefinition.of(context).color;
    return new Container(
      color: color,
      child: new Column(
        children: [
          new RaisedButton(
              child: new Text("next"),
              onPressed: () {
                Navigator.push(
                  context,
                  new MaterialPageRoute(builder: (context) => new SecondPage()),
                );
              }),
        ],
      ),
    );
  }
}
void main() => runApp(
      new MaterialApp(
        builder: (context, child) => new SafeArea(
              child: new ColorDefinition(child: child),
            ),
        home: new FirstPage(),
      ),
    );

如果您使用了InheritedWidget,您不必担心观察您推送的页面的弹出,这对基本的用例将有效,但在更复杂的情况下可能会遇到问题。

0