felangel / flow_builder

Flutter Flows made easy! A Flutter package which simplifies navigation flows with a flexible, declarative API.
https://pub.dev/packages/flow_builder
MIT License
389 stars 63 forks source link

[question] How use Dialog #32

Open andrea689 opened 3 years ago

andrea689 commented 3 years ago

Hi @felangel, is there a way to push and pop a Dialog based on state like a Page?

andrea689 commented 3 years ago

How does this solution look to you? Is there a cleaner way?

class PlayerFlow extends StatefulWidget {
  static Route<int> route() {
    return MaterialPageRoute(
      builder: (_) => PlayerFlow(),
    );
  }

  @override
  _PlayerFlowState createState() => _PlayerFlowState();
}

class _PlayerFlowState extends State<PlayerFlow> {
  FlowController<int> controller;

  @override
  void initState() {
    super.initState();
    controller = FlowController(0);
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return FlowBuilder<int>(
      controller: controller,
      onGeneratePages: (int state, List<Page> pages) {
        if (state == 1) {
          showDialog(
            context: context,
            child: MyDialog(
              onDismiss: () {
                Navigator.of(context).pop();
                controller.update((_) => 0);
              },
            ),
            useRootNavigator: false,
          );
        }
        return [
          PlayerPage.page(),
        ];
      },
    );
  }
}

class MyDialog extends StatelessWidget {
  final Function() onDismiss;

  const MyDialog({
    Key key,
    @required this.onDismiss,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onDismiss,
      child: WillPopScope(
        onWillPop: () async {
          onDismiss();
          return false;
        },
        child: Dialog(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Text('Hello, I\'m a dialog'),
              RaisedButton(
                onPressed: onDismiss,
                child: Text('Close'),
              )
            ],
          ),
        ),
      ),
    );
  }
}
SAGARSURI commented 1 year ago

Is this the preferred answer to this problem? @felangel

Gene-Dana commented 1 year ago

Is this the preferred answer to this problem?

Normally one doesn't use state to drive dialogs since they are generally associated with an action that pops them.

Alert: battery is low

low power mode
or ignore

Instead are you looking to implement a snackbar?

Here is an example of using state to drive a snackbar https://github.com/felangel/bloc/blob/13597e2ba7780e3e0bf0581050944b1f9c7b1c08/examples/flutter_todos/lib/todos_overview/view/todos_overview_page.dart#L40-L83

          BlocListener<TodosOverviewBloc, TodosOverviewState>(
            listenWhen: (previous, current) =>
                previous.status != current.status,
            listener: (context, state) {
              if (state.status == TodosOverviewStatus.failure) {
                ScaffoldMessenger.of(context)
                  ..hideCurrentSnackBar()
                  ..showSnackBar(
                    SnackBar(
                      content: Text(l10n.todosOverviewErrorSnackbarText),
                    ),
                  );
              }
            },
          ),
          BlocListener<TodosOverviewBloc, TodosOverviewState>(
            listenWhen: (previous, current) =>
                previous.lastDeletedTodo != current.lastDeletedTodo &&
                current.lastDeletedTodo != null,
            listener: (context, state) {
              final deletedTodo = state.lastDeletedTodo!;
              final messenger = ScaffoldMessenger.of(context);
              messenger
                ..hideCurrentSnackBar()
                ..showSnackBar(
                  SnackBar(
                    content: Text(
                      l10n.todosOverviewTodoDeletedSnackbarText(
                        deletedTodo.title,
                      ),
                    ),
                    action: SnackBarAction(
                      label: l10n.todosOverviewUndoDeletionButtonText,
                      onPressed: () {
                        messenger.hideCurrentSnackBar();
                        context
                            .read<TodosOverviewBloc>()
                            .add(const TodosOverviewUndoDeletionRequested());
                      },
                    ),
                  ),
                );
            },
          ),

Here you can in the same example a fullscreen dialog https://github.com/felangel/bloc/blob/13597e2ba7780e3e0bf0581050944b1f9c7b1c08/examples/flutter_todos/lib/edit_todo/view/edit_todo_page.dart#L9-L23