simple_loading_dialog
A simple full-screen loading dialog for Flutter.
Features
- Simple full-screen loading dialog.
- Blocks user input while waiting for a
Futureto complete. - Rethrows exceptions on error.
- Customizable dialog appearance.
- Returns the result of the
Future.
Demo
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'),
],
),
),
);
Using SimpleLoadingDialogTheme (recommended)
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.