【问题标题】:How to call setState (rebuild page), after pop of PopUpWindow?弹出PopUpWindow后如何调用setState(重建页面)?
【发布时间】:2020-02-23 23:45:55
【问题描述】:

当弹出窗口弹出时,我正在尝试使用 Navigator.pop(context) 更新/重建弹出窗口下方的路线。在弹出窗口中,用户可以将某些内容添加到列表中,以及下方(页面)的路线,添加的项目显示在 ListView 中。所以更具体地说,我需要我的 ListView 与实际列表保持同步。但是我还没有尝试过,但没有任何效果。

如前所述,我已经尝试了很多东西,包括: didPopNext()(使用 RouteAware)、changedExternalState(我无法完全掌握)、尝试传递仅包含 setState(() {}) 的函数以及其他内容。

希望有人可以帮助我在弹出弹出窗口时如何重建 ListView。

提前致谢。

这个例子应该很好地总结了我的问题(无法显示实际代码,因为它已经超过 2000 行,但问题的核心元素应该在这里):

import 'package:flutter/material.dart';

void main() => runApp(new MaterialApp(
  home: MyPage()));

class PopupLayout extends ModalRoute<void> {
  @override
  Duration get transitionDuration => Duration(milliseconds: 300);
  @override
  bool get opaque => false;
  @override
  bool get barrierDismissible => false;
  @override
  bool get semanticsDismissible => true;
  @override
  Color get barrierColor =>
      bgColor == null ? Colors.black.withOpacity(0.5) : bgColor;
  @override
  String get barrierLabel => null;
  @override
  bool get maintainState => false;


  double top;
  double bottom;
  double left;
  double right;
  Color bgColor;
  final Widget child;

  PopupLayout(
      {Key key,
      this.bgColor,
      @required this.child,
      this.top,
      this.bottom,
      this.left,
      this.right});

  @override
  Widget buildPage(
    BuildContext context,
    Animation<double> animation,
    Animation<double> secondaryAnimation,
  ) {
    if (top == null) this.top = 10;
    if (bottom == null) this.bottom = 20;
    if (left == null) this.left = 20;
    if (right == null) this.right = 20;

    return GestureDetector(
      onTap: () {},
      child: Material(
        type: MaterialType.transparency,
        child: _buildOverlayContent(context),
      ),
    );
  }
  Widget _buildOverlayContent(BuildContext context) {
    return Container(
      margin: EdgeInsets.only(
          bottom: this.bottom,
          left: this.left,
          right: this.right,
          top: this.top),
      child: child,
    );
  }

  @override
  Widget buildTransitions(BuildContext context, Animation<double> animation,
    Animation<double> secondaryAnimation, Widget child) {
    return FadeTransition(
      opacity: animation,
      child: ScaleTransition(
        scale: animation,
        child: child,
      ),
    );
  }
}

class PopupContent extends StatefulWidget {
  final Widget content;
  PopupContent({
    Key key,
    this.content,
  }) : super(key: key);
  _PopupContentState createState() => _PopupContentState();
}

class _PopupContentState extends State<PopupContent> {
  @override
  void initState() {
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return Container(
      child: widget.content,
    );
  }
}

popupContent(BuildContext context, Widget widget,
      {BuildContext popupContext}) {
  Navigator.push(
    context,
    PopupLayout(
      top: 120,
      left: 20,
      right: 20,
      bottom: 120,
      child: PopupContent(
        content: Scaffold(
          backgroundColor: Colors.white,
          resizeToAvoidBottomInset: false,
          body: widget,
        ),
      ),
    ),
  );
}

Widget popupWidget(BuildContext context) {
  return new Container(
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Text("This is a popupPage"),
          FlatButton(
          onPressed: () {
            list.add("Irrelevant");
            Navigator.pop(context); //The rebuild of the page underneath, needs to be called when this pops
          },
      child: Text("Press me to change text on home page"),
        ),
      ]
    ),
  );
}

List list = [];

class MyPage extends StatefulWidget {
  @override
  createState() => MyPageState();
}

class MyPageState extends State<MyPage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Center(
            child: Container(
              width: 300,
              height: 400,
              child: ListView.builder(
                itemCount: list.length,
                itemBuilder: (BuildContext context, int index) {
                  return Center(
                    child: Text(index.toString()),
                  );
                },
              ),
            ),
          ),
          Center(
            child: FlatButton(
              onPressed: () {
                popupContent(context, popupWidget(context));
              },
              child: Text("Press me for popup window"),
            ),
          ),
          Center(
            child: FlatButton(
              onPressed: () {
                setState(() {});
              },
              child: Text("Press me to rebuild page (setState)"),
            ),
          ),
        ]
      ),
    );
  }
}

【问题讨论】:

    标签: flutter dart popupwindow setstate


    【解决方案1】:

    您可以在 MyPage 中添加一个函数并将其传递给您的 popUpWidget。代码:

    import 'package:flutter/material.dart';
    
    void main() => runApp(new MaterialApp(home: MyPage()));
    
    class PopupLayout extends ModalRoute<void> {
      @override
      Duration get transitionDuration => Duration(milliseconds: 300);
      @override
      bool get opaque => false;
      @override
      bool get barrierDismissible => false;
      @override
      bool get semanticsDismissible => true;
      @override
      Color get barrierColor =>
          bgColor == null ? Colors.black.withOpacity(0.5) : bgColor;
      @override
      String get barrierLabel => null;
      @override
      bool get maintainState => false;
    
      double top;
      double bottom;
      double left;
      double right;
      Color bgColor;
      final Widget child;
    
      PopupLayout(
          {Key key,
          this.bgColor,
          @required this.child,
          this.top,
          this.bottom,
          this.left,
          this.right});
    
      @override
      Widget buildPage(
        BuildContext context,
        Animation<double> animation,
        Animation<double> secondaryAnimation,
      ) {
        if (top == null) this.top = 10;
        if (bottom == null) this.bottom = 20;
        if (left == null) this.left = 20;
        if (right == null) this.right = 20;
    
        return GestureDetector(
          onTap: () {},
          child: Material(
            type: MaterialType.transparency,
            child: _buildOverlayContent(context),
          ),
        );
      }
    
      Widget _buildOverlayContent(BuildContext context) {
        return Container(
          margin: EdgeInsets.only(
              bottom: this.bottom,
              left: this.left,
              right: this.right,
              top: this.top),
          child: child,
        );
      }
    
      @override
      Widget buildTransitions(BuildContext context, Animation<double> animation,
          Animation<double> secondaryAnimation, Widget child) {
        return FadeTransition(
          opacity: animation,
          child: ScaleTransition(
            scale: animation,
            child: child,
          ),
        );
      }
    }
    
    class PopupContent extends StatefulWidget {
      final Widget content;
      PopupContent({
        Key key,
        this.content,
      }) : super(key: key);
      _PopupContentState createState() => _PopupContentState();
    }
    
    class _PopupContentState extends State<PopupContent> {
      @override
      void initState() {
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Container(
          child: widget.content,
        );
      }
    }
    
    popupContent(BuildContext context, Widget widget, {BuildContext popupContext}) {
      Navigator.push(
        context,
        PopupLayout(
          top: 120,
          left: 20,
          right: 20,
          bottom: 120,
          child: PopupContent(
            content: Scaffold(
              backgroundColor: Colors.white,
              resizeToAvoidBottomInset: false,
              body: widget,
            ),
          ),
        ),
      );
    }
    
    Widget popupWidget(BuildContext context, Function callback) {
      //Pass The Function Here //////////////////////
      return new Container(
        child:
            Column(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
          Text("This is a popupPage"),
          FlatButton(
            onPressed: () {
              list.add("Irrelevant");
              callback(); // Call It Here /////////////////////////
              Navigator.pop(
                  context); //The rebuild of the page underneath, needs to be called when this pops
            },
            child: Text("Press me to change text on home page"),
          ),
        ]),
      );
    }
    
    List list = [];
    
    class MyPage extends StatefulWidget {
      @override
      createState() => MyPageState();
    }
    
    class MyPageState extends State<MyPage> {
      //The Calback Function //////////////////////////
      void callback() {
        setState(() {});
      }
    
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          body: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Center(
                  child: Container(
                    width: 300,
                    height: 400,
                    child: ListView.builder(
                      itemCount: list.length,
                      itemBuilder: (BuildContext context, int index) {
                        return Center(
                          child: Text(index.toString()),
                        );
                      },
                    ),
                  ),
                ),
                Center(
                  child: FlatButton(
                    onPressed: () {
                      popupContent(context, popupWidget(context, this.callback)); //Passing the Function here ////////////
                    },
                    child: Text("Press me for popup window"),
                  ),
                ),
                Center(
                  child: FlatButton(
                    onPressed: () {
                      setState(() {});
                    },
                    child: Text("Press me to rebuild page (setState)"),
                  ),
                ),
              ]),
        );
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-08-22
      • 1970-01-01
      • 2014-02-23
      • 1970-01-01
      • 2016-12-31
      • 1970-01-01
      • 2011-12-25
      • 1970-01-01
      • 2021-01-02
      相关资源
      最近更新 更多