Skip to content

Instantly share code, notes, and snippets.

@DavBfr
Last active May 2, 2022 21:03
Show Gist options
  • Save DavBfr/a07e7f4ceefff225c9ed0b9d276ec5a0 to your computer and use it in GitHub Desktop.
Save DavBfr/a07e7f4ceefff225c9ed0b9d276ec5a0 to your computer and use it in GitHub Desktop.
Progres indicator
// Test at:
// https://dartpad.dev/?id=a07e7f4ceefff225c9ed0b9d276ec5a0
import 'dart:async';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return OutlinedButton(
child: const Text('Start!'),
onPressed: () async {
final a = StreamController<double?>();
final b = StreamController<Widget?>();
final c = Completer<void>();
progress(
context: context,
title: const Text('Uploading files'),
value: a.stream,
message: b.stream,
result: c.future,
);
// Start the progression at 0
a.add(0);
const count = 10;
for (var file = 0; file < count; file++) {
b.add(Text('Uploading photo $file of $count'));
// Do some async work here
await Future.delayed(const Duration(seconds: 1));
// Increment the progress bar (from 0.0 to 1.0)
a.add((file + 1) / count);
}
// The progress is done
c.complete();
});
}
}
Future<T?> progress<T>({
required BuildContext context,
required Future<T> result,
Stream<double?>? value,
Stream<Widget?>? message,
Widget? title,
}) async {
BuildContext? innerContext;
showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
innerContext = context;
return AlertDialog(
title: title,
content: SingleChildScrollView(
child: _ProgressIndicator(value, message),
),
);
},
);
try {
return await result;
} finally {
if (innerContext != null) {
Navigator.pop(innerContext!);
}
}
}
class _ProgressIndicator extends StatefulWidget {
const _ProgressIndicator(this.value, this.message);
final Stream<double?>? value;
final Stream<Widget?>? message;
@override
State<_ProgressIndicator> createState() => _ProgressIndicatorState();
}
class _ProgressIndicatorState extends State<_ProgressIndicator> {
StreamSubscription<double?>? _sub;
StreamSubscription<Widget?>? _subMessage;
double? _value;
Widget? _message;
@override
void initState() {
_sub = widget.value?.listen((event) {
if (mounted) {
setState(() {
_value = event;
});
}
});
_subMessage = widget.message?.listen((event) {
if (mounted) {
setState(() {
_message = event;
});
}
});
super.initState();
}
@override
void dispose() {
_sub?.cancel();
_subMessage?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ListBody(
children: <Widget>[
LinearProgressIndicator(value: _value),
const SizedBox(height: 16),
if (_message != null) Center(child: _message!),
],
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment