【问题标题】:Flutter - Show only one Dialog at the timeFlutter - 一次只显示一个对话框
【发布时间】:2023-04-04 16:56:01
【问题描述】:

我正在开发一个使用多个对话框用于多种目的的颤振应用程序。 在我们的代码中,在某些情况下用户可以打开一个对话框。在此对话框中,有一些按钮也会打开另一个对话框。结果是 2 个对话框相互叠加,背景屏幕非常暗。 我们想做的是一次只显示一个对话框。我们怎样才能做到这一点?

这里有一个简单的代码来说明我们的问题:

class MyScreen extends StatelessWidget {
  @override
  build(BuildContext context) {
    return FlatButton(
      child: Text('Button'),
      onPressed: () async {
        final resultDialog = await showDialog<ResultDialog1>(
          context: context,
          builder: (BuildContext context) => MyFirstDialog(),
        );
        // Do some stuff with the result, so this part of the tree cannot be destroyed
      },
    );
  }
}

class MyFirstDialog extends StatelessWidget {
  @override
  build(BuildContext context) {
    return FlatButton(
      child: Text('Button in first dialog'),
      onPressed: () async {
        final resultDialog = await showDialog<ResultDialog2>(
          context: context,
          builder: (BuildContext context) => MySecondDialog(),  // <- This will appear on top of the first dialog
        );
        // Do some stuff with the result, so this part of the tree cannot be destroyed
      },
    );
  }
}

class MySecondDialog extends StatelessWidget {
  @override
  build(BuildContext context) {
    return Text('Second Dialog');
  }
}

【问题讨论】:

    标签: flutter dart dialog flutter-web


    【解决方案1】:

    让我给你一个小部件

    
    class MultiDialog extends StatefulWidget {
      final Widget child;
    
      const MultiDialog({Key key, this.child}) : super(key: key);
      @override
      _MultiDialogState createState() => _MultiDialogState();
    
      static void addDialog(
          {@required BuildContext context, @required Widget dialog}) {
        assert(context != null, "the context cannot be null");
        assert(dialog != null, "the dialog cannot be null");
        context.findAncestorStateOfType<_MultiDialogState>()._addDialog(dialog);
      }
    
      static void remove({@required BuildContext context}) {
        assert(context != null, "the context cannot be null");
        context.findAncestorStateOfType<_MultiDialogState>()._remove();
      }
    }
    
    class _MultiDialogState extends State<MultiDialog> {
      final _allDialogs = <Widget>[];
    
      void _addDialog<T>(Widget dialog) {
        assert(dialog != null, "The dialog cannot be null");
        setState(() {
          _allDialogs.add(dialog);
        });
      }
    
      void _remove() {
        if (_allDialogs.isEmpty) {
          print("No dialogs to remove");
          return;
        }
        setState(() {
          _allDialogs.removeLast();
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Stack(
          children: [
            widget.child,
            if (_allDialogs.isNotEmpty) _allDialogs.last,
          ],
        );
      }
    }
    

    当你想添加一个对话框时,只需调用

    MultiDialog.addDialog(
      context: context,
      dialog: AlertDialog(),
    );
    

    调用Navigator.pop 删除对话框,如果您推送的另一个对话框存在,它将显示,您可以进一步将它们全部弹出结果,PS:此代码未经测试,请告诉我如果这对你有用,在 cmets 中

    调用MultiDialog.remove(context:context)弹出可见对话框并带回上一个对话框,

    如果您收到一个错误,即在 null 上调用 addDialog,这是因为颤振是如何工作的,在 MultiDialog 使用 Builder 引入新的 context 之后,使用它调用 showDialogPS:以上代码已经过测试

    【讨论】:

    • 我没能成功。我有错误TypeError: Cannot read property 'Symbol(_addDialog)' of null,我认为这是因为显示对话框中的小部件没有与前一个屏幕共享上下文(因此没有MultiDialog)而且我觉得这段代码不会关闭前一个对话框一个新的添加对吗?
    • 是的,我过度设计了之前的代码,检查新的工作代码
    【解决方案2】:

    我从导致对话框弹出的事件中制作了一个流,并使用 rx darts 排气图来等待结果(我已经在使用 rxdart)

        dialogEventStream
        .exhaustMap((_) => maybeShowDialog().asStream())
        .listen((_) {});
    
    
      Future<bool> maybeShowOfflineModeDialog() async {
        final isOfflineModeEnabled = await _sharedPreferencesService.isOfflineModeEnabled();
        if (!isOfflineModeEnabled) {
          final isLoginOffline = await _navigationService.showDialog(NoConnectionDialog());
          if (isLoginOffline == true) {
            await _sharedPreferencesService.setIsOfflineModeEnabled(isOfflineModeEnabled: true);
            return await _navigationService.pushReplacement(AppShellOffline.routeName) ?? true;
          } else {
            return false;
          }
        }
        return false;
      }
    

    类似的东西

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多