simple_loading_dialog

A simple full-screen loading dialog for Flutter.

Features

  • Simple full-screen loading dialog.
  • Blocks user input while waiting for a Future to complete.
  • Rethrows exceptions on error.
  • Customizable dialog appearance.
  • Returns the result of the Future.

Demo

simple_loading_dialog

Installation

To use this package, add simple_loading_dialog as a dependency in your pubspec.yaml file.

Usage

Showing the dialog

To show the dialog, use the showSimpleLoadingDialog function:

final result = await showSimpleLoadingDialog<String>(
  context: context,
  future: myFutureFunction,
);

This will display a full-screen progress dialog while waiting for the myFutureFunction to complete. Once the Future completes, the result will be returned, and the dialog will be dismissed.

Customizing the appearance

The appearance of the dialog can be customized by passing a dialogBuilder:

await showSimpleLoadingDialog<void>(
  context: context,
  future: myFutureFunction,
  dialogBuilder: (context, _) => AlertDialog(
    content: Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        CircularProgressIndicator(),
        SizedBox(height: 16),
        Text('Custom message'),
      ],
    ),
  ),
);

To customize the appearance of the dialog using the SimpleLoadingDialogTheme extension, define a theme in your app and pass it to the showSimpleLoadingDialog function:

MaterialApp(
  title: 'My App',
  theme: ThemeData(
    useMaterial3: true,
    colorSchemeSeed: Colors.blue,
    extensions: [
      SimpleLoadingDialogTheme(
        dialogBuilder: (context, message) {
          return AlertDialog(
            content: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                const SizedBox(height: 16),
                const CircularProgressIndicator(),
                const SizedBox(height: 16),
                Text(message),
                const SizedBox(height: 16),
              ],
            ),
          );
        },
      ),
    ],
  ),
  home: MyHomePage(),
);

final result = await showSimpleLoadingDialog<String>(
  context: context,
  future: myFutureFunction,
  message: "Saving...",
);

Handling errors

If an error occurs while waiting for the Future to complete, the exception will be rethrown. To handle the error, use a try-catch block:

try {
  await showSimpleLoadingDialog<void>(
    context: context,
    future: myFutureFunction,
  );
} catch (e) {
  // Handle the error.
}

Optional: Using a wrapper function to return a Result type

You can define a wrapper function to show a loading dialog and return a Result type.

Step 1: Define the Result class

sealed class Result<T> {
  const Result();
}

class Success<T> extends Result<T> {
  const Success({required this.value});

  final T value;
}

class Failure<T> extends Result<T> {
  const Failure({required this.error, this.stackTrace});

  final Object error;
  final StackTrace? stackTrace;
}

Step 2: Create the wrapper function

Future<Result<T>> showSimpleLoadingDialogWithResult<T>({
  required BuildContext context,
  required Future<T> Function() future,
  DialogBuilder? dialogBuilder,
  String message = 'Loading...',
  bool barrierDismissible = false,
}) async {
  try {
    final res = await showSimpleLoadingDialog(
      context: context,
      future: future,
      dialogBuilder: dialogBuilder,
      message: message,
      barrierDismissible: barrierDismissible,
    );

    return Success(value: res);
  } catch (err, stack) {
    return Failure(error: err, stackTrace: stack);
  }
}

Step 3: Show the dialog and handle the result

ElevatedButton(
  onPressed: () async {
    final result = await showSimpleLoadingDialogWithResult<String>(
      context: context,
      future: () async {
        await Future<void>.delayed(const Duration(seconds: 1));
        // return 'Hello';
        throw Exception('Error');
      },
    );

    if (context.mounted) {
      switch (result) {
        case Success():
          context.showMessageSnackBar('Success result: ${result.value}');
        case Failure():
          context.showMessageSnackBar('Failed result: ${result.error}');
      }
    }
  },
  child: const Text('Optional: Show loading dialog with result'),
);

License

This package is licensed under the MIT License. See the LICENSE file for details.