Global dialog class for whole app in Flutter
Note:- This solution is without using Cupertino
To Show the progress dialog
ProgressDialog progressDialog;
onTap: (){
progressDialog = new ProgressDialog(context);
progressDialog.show();
/// progressDialog.hide(); Use to hide the progress
/// progressDialog.isShowing(); Use to check status of dialog
}
onTap: (){
progressDialog = new ProgressDialog(context);
progressDialog.show();
/// progressDialog.hide(); Use to hide the progress
/// progressDialog.isShowing(); Use to check status of dialog
}
You need these 3 classes to achieve this and you can copy these classes in you utils folder and ready to use.
loading_view.dart
import 'package:flutter/material.dart';
import 'dart:math' as math;
class SimpleProgressDialog extends StatefulWidget {
SimpleProgressDialog(double size, {this.color: Colors.grey, this.duration: const Duration(milliseconds: 600)}): assert(size != null), _size = new Size(size, size);
final Size _size;
final Color color;
final Duration duration;
@override
State<StatefulWidget> createState() {
return new _SimpleProgressDialogState();
}
}
class _SimpleProgressDialogState extends State<SimpleProgressDialog> with TickerProviderStateMixin {
AnimationController _animationController;
@override
void initState() {
super.initState();
_animationController = new AnimationController(value: 1.0, duration: widget.duration, vsync: this);
_animationController.forward(from: 0.0);
_animationController.repeat();
}
@override
Widget build(BuildContext context) {
return new CustomPaint(painter: new _LoadingViewPainter(repaint: _animationController, color: widget.color), size: widget._size,);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
}
class _LoadingViewPainter extends CustomPainter {
static const Color color1= Color(0x66bbbbbb);
_LoadingViewPainter({@required AnimationController repaint, this.color: color1,}) : animation = new IntTween(begin: 0, end: _LoadingViewPainter._lineCount)
.animate(repaint),
super(repaint: repaint);
final Animation animation;
final Color color;
Paint _paint;
static int _lineCount = 12;
static double _degreePerLine = (2 * math.pi) / _lineCount;
@override
void paint(Canvas canvas, Size size) {
double min = math.min(size.width, size.height);
double width = min / 12, height = min / 6;
_paint ??= new Paint()..color = color..strokeWidth = width..strokeCap = StrokeCap.round;
canvas.saveLayer(Rect.fromLTRB(0.0, 0.0, size.width, size.height), _paint);
double radians = animation.value * _degreePerLine;
canvas.translate(min / 2, min / 2);
canvas.rotate(radians);
for (int i = 0; i < _lineCount; i++) {
canvas.rotate(_degreePerLine);
_paint.color = _paint.color.withAlpha(255 * (i + 1) ~/ _lineCount);
canvas.translate(0.0, -min / 2 + width / 2);
canvas.drawLine(Offset.zero, new Offset(0.0, height), _paint);
canvas.translate(0.0, min / 2 - width / 2);
}
canvas.restore();
}
@override
bool shouldRepaint(_LoadingViewPainter oldDelegate) {
return color != oldDelegate.color;
}
}
import 'dart:math' as math;
class SimpleProgressDialog extends StatefulWidget {
SimpleProgressDialog(double size, {this.color: Colors.grey, this.duration: const Duration(milliseconds: 600)}): assert(size != null), _size = new Size(size, size);
final Size _size;
final Color color;
final Duration duration;
@override
State<StatefulWidget> createState() {
return new _SimpleProgressDialogState();
}
}
class _SimpleProgressDialogState extends State<SimpleProgressDialog> with TickerProviderStateMixin {
AnimationController _animationController;
@override
void initState() {
super.initState();
_animationController = new AnimationController(value: 1.0, duration: widget.duration, vsync: this);
_animationController.forward(from: 0.0);
_animationController.repeat();
}
@override
Widget build(BuildContext context) {
return new CustomPaint(painter: new _LoadingViewPainter(repaint: _animationController, color: widget.color), size: widget._size,);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
}
class _LoadingViewPainter extends CustomPainter {
static const Color color1= Color(0x66bbbbbb);
_LoadingViewPainter({@required AnimationController repaint, this.color: color1,}) : animation = new IntTween(begin: 0, end: _LoadingViewPainter._lineCount)
.animate(repaint),
super(repaint: repaint);
final Animation animation;
final Color color;
Paint _paint;
static int _lineCount = 12;
static double _degreePerLine = (2 * math.pi) / _lineCount;
@override
void paint(Canvas canvas, Size size) {
double min = math.min(size.width, size.height);
double width = min / 12, height = min / 6;
_paint ??= new Paint()..color = color..strokeWidth = width..strokeCap = StrokeCap.round;
canvas.saveLayer(Rect.fromLTRB(0.0, 0.0, size.width, size.height), _paint);
double radians = animation.value * _degreePerLine;
canvas.translate(min / 2, min / 2);
canvas.rotate(radians);
for (int i = 0; i < _lineCount; i++) {
canvas.rotate(_degreePerLine);
_paint.color = _paint.color.withAlpha(255 * (i + 1) ~/ _lineCount);
canvas.translate(0.0, -min / 2 + width / 2);
canvas.drawLine(Offset.zero, new Offset(0.0, height), _paint);
canvas.translate(0.0, min / 2 - width / 2);
}
canvas.restore();
}
@override
bool shouldRepaint(_LoadingViewPainter oldDelegate) {
return color != oldDelegate.color;
}
}
progress_dialog.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app/utils/tip_dialog.dart';
bool _isShowing = false;
class ProgressDialog {
BuildContext _buildContext, _context;
ProgressDialog(BuildContext buildContext) {
_buildContext = buildContext;
}
bool isShowing() {
return _isShowing;
}
void hide() {
if (_isShowing) {
_isShowing = false;
Navigator.of(_context).pop();
debugPrint('ProgressDialog1 dismissed');
}
}
void show() {
if (!_isShowing) {
_isShowing = true;
debugPrint('ProgressDialog1 shown');
showDialog<dynamic>(
context: _buildContext,
barrierDismissible: false,
builder: (BuildContext context) {
_context = context;
return TipDialogConnector(
builder: (context, tipController) {
return TipDialog(type: TipDialogType.LOADING, tip: "");
},
);
},
);
}
}
}
import 'package:flutter/material.dart';
import 'package:flutter_app/utils/tip_dialog.dart';
bool _isShowing = false;
class ProgressDialog {
BuildContext _buildContext, _context;
ProgressDialog(BuildContext buildContext) {
_buildContext = buildContext;
}
bool isShowing() {
return _isShowing;
}
void hide() {
if (_isShowing) {
_isShowing = false;
Navigator.of(_context).pop();
debugPrint('ProgressDialog1 dismissed');
}
}
void show() {
if (!_isShowing) {
_isShowing = true;
debugPrint('ProgressDialog1 shown');
showDialog<dynamic>(
context: _buildContext,
barrierDismissible: false,
builder: (BuildContext context) {
_context = context;
return TipDialogConnector(
builder: (context, tipController) {
return TipDialog(type: TipDialogType.LOADING, tip: "");
},
);
},
);
}
}
}
tip_dialog.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_app/utils/loading_view.dart';
enum TipDialogType { NOTHING, LOADING, SUCCESS, FAIL, INFO }
class TipDialog extends StatelessWidget {
TipDialog({Key key, TipDialogType type: TipDialogType.NOTHING, this.tip}): assert(type != null),
icon = type == TipDialogType.NOTHING ? null : SimpleProgressDialog(50.0, color: Colors.white),
bodyBuilder = null, color = Colors.red.withOpacity(0.2), super(key: key);
TipDialog.customIcon({Key key, this.icon, this.tip}): assert(icon != null || tip != null), bodyBuilder = null, color = Colors.red.withOpacity(0.2), super(key: key);
TipDialog.builder({Key key, this.bodyBuilder, this.color: Colors.black}): assert(bodyBuilder != null), tip = null, icon = null, super(key: key);
final String tip;
final Widget icon;
final WidgetBuilder bodyBuilder;
final Color color;
Widget _buildBody() {
List<Widget> childs = [];
if (icon != null) {
childs.add(new Padding(
padding: tip == null
? const EdgeInsets.all(20.0)
: const EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0),
child: icon,
));
}
if (tip != null) {
childs.add(new Padding(
padding: icon == null
? const EdgeInsets.fromLTRB(8.0, 0.0, 8.0, 0.0)
: const EdgeInsets.fromLTRB(8.0, 0.0, 8.0, 8.0),
child: new Text(
tip,
textAlign: TextAlign.center,
style: new TextStyle(color: Colors.white, fontSize: 15.0),
textDirection: TextDirection.ltr,
),
));
}
return new Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: childs,
);
}
@override
Widget build(BuildContext context) {
return new ClipRRect(
borderRadius: new BorderRadius.circular(15.0),
child: new Container(
constraints: icon == null || tip == null
? new BoxConstraints(minHeight: 50.0, minWidth: 100.0)
: new BoxConstraints(minHeight: 90.0, minWidth: 120.0),
color: color,
child: bodyBuilder == null ? _buildBody() : bodyBuilder(context),
),
);
}
}
class TipDialogContainer extends StatefulWidget {
TipDialogContainer(
{Key key, @required this.child, this.duration: const Duration(seconds: 2), this.maskAlpha: 0.3}) : super(key: key);
final Widget child;
final Duration duration;
final double maskAlpha;
@override
State<StatefulWidget> createState() {
return new TipDialogContainerState();
}
}
class TipDialogContainerState extends State<TipDialogContainer>
with TickerProviderStateMixin {
Timer _timer;
bool _show;
AnimationController _animationController;
Animation _scaleAnimation;
VoidCallback _animationListener;
bool _prepareDismiss = false;
Widget _tipDialog;
bool _isAutoDismiss;
bool get isShow => _show;
void dismiss() {
setState(() {
if (_animationController.isAnimating) {
_show = false;
_animationController.stop(canceled: true);
} else {
_prepareDismiss = true;
_animationController.reverse();
}
});
}
void show({@required Widget tipDialog, bool isAutoDismiss: true}) {
assert(tipDialog != null);
_tipDialog = tipDialog;
_isAutoDismiss = isAutoDismiss;
setState(() {
_start();
_show = true;
});
}
@override
void initState() {
super.initState();
_show = false;
_animationController = new AnimationController(
value: 0.0, duration: new Duration(milliseconds: 200), vsync: this);
_animationListener = () {
if (_animationController.value == 0.0 && _prepareDismiss) {
setState(() {
_show = false;
_prepareDismiss = false;
});
}
};
_animationController.addListener(_animationListener);
_scaleAnimation =
new Tween(begin: 0.95, end: 1.0).animate(_animationController);
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
if (_show)
_start();
}
void _start() {
_animationController.forward(from: 0.0);
if (_isAutoDismiss) {
if (_timer != null) {
_timer.cancel();
if (_show) {
dismiss();
}
_timer = null;
}
_timer = new Timer(widget.duration, () {
dismiss();
_timer = null;
});
}
}
@override
void dispose() {
if (_timer != null) {
_timer.cancel();
if (_show)
dismiss();
}
_animationController.removeListener(_animationListener);
_animationController.dispose();
super.dispose();
}
Widget _buildMaskLayer() {
return new LayoutBuilder(builder: (context, size) {
return new FadeTransition(
opacity: _animationController,
child: new Container(width: size.maxWidth, height: size.maxHeight,color: Colors.black.withAlpha(widget.maskAlpha * 255 ~/ 1),
),
);
});
}
@override
Widget build(BuildContext context) {
List<Widget> widgets = [widget.child];
if (_show) {
widgets.add(_buildMaskLayer());
widgets.add(new ScaleTransition(scale: _scaleAnimation,
child: new FadeTransition(opacity: _animationController, child: _tipDialog,
),
));
}
return new _TipDialogProvider(
controller: new TipDialogController(showCallback: show, dismissCallback: dismiss),
child: new Stack(alignment: Alignment.center, children: widgets)
);
}
}
typedef void ShowTipDialogCallback({@required Widget tipDialog, bool isAutoDismiss});
typedef void DismissTipDialogCallback();
class TipDialogController {
final ShowTipDialogCallback showCallback;
final DismissTipDialogCallback dismissCallback;
TipDialogController({Key key, ShowTipDialogCallback showCallback, DismissTipDialogCallback dismissCallback})
: showCallback = showCallback,
dismissCallback = dismissCallback;
show({@required Widget tipDialog, bool isAutoDismiss: true}) {
showCallback(tipDialog: tipDialog, isAutoDismiss: isAutoDismiss);
}
dismiss() {
dismissCallback();
}
}
class _TipDialogProvider extends InheritedWidget {
final TipDialogController controller;
_TipDialogProvider({Key key, @required this.controller, @required Widget child})
: assert(controller != null), assert(child != null), super(key: key, child: child);
static TipDialogController of(BuildContext context) {
final _TipDialogProvider scope =context.inheritFromWidgetOfExactType(_TipDialogProvider);
return scope?.controller;
}
@override
bool updateShouldNotify(_TipDialogProvider oldWidget) {
return controller != oldWidget.controller;
}
}
typedef Widget TipDialogBuilder(BuildContext context, TipDialogController controller);
class TipDialogConnector extends StatelessWidget {
final TipDialogBuilder builder;
TipDialogConnector({this.builder});
@override
Widget build(BuildContext context) {
return builder(context, _TipDialogProvider.of(context));
}
}
import 'package:flutter/material.dart';
import 'package:flutter_app/utils/loading_view.dart';
enum TipDialogType { NOTHING, LOADING, SUCCESS, FAIL, INFO }
class TipDialog extends StatelessWidget {
TipDialog({Key key, TipDialogType type: TipDialogType.NOTHING, this.tip}): assert(type != null),
icon = type == TipDialogType.NOTHING ? null : SimpleProgressDialog(50.0, color: Colors.white),
bodyBuilder = null, color = Colors.red.withOpacity(0.2), super(key: key);
TipDialog.customIcon({Key key, this.icon, this.tip}): assert(icon != null || tip != null), bodyBuilder = null, color = Colors.red.withOpacity(0.2), super(key: key);
TipDialog.builder({Key key, this.bodyBuilder, this.color: Colors.black}): assert(bodyBuilder != null), tip = null, icon = null, super(key: key);
final String tip;
final Widget icon;
final WidgetBuilder bodyBuilder;
final Color color;
Widget _buildBody() {
List<Widget> childs = [];
if (icon != null) {
childs.add(new Padding(
padding: tip == null
? const EdgeInsets.all(20.0)
: const EdgeInsets.fromLTRB(0.0, 8.0, 0.0, 8.0),
child: icon,
));
}
if (tip != null) {
childs.add(new Padding(
padding: icon == null
? const EdgeInsets.fromLTRB(8.0, 0.0, 8.0, 0.0)
: const EdgeInsets.fromLTRB(8.0, 0.0, 8.0, 8.0),
child: new Text(
tip,
textAlign: TextAlign.center,
style: new TextStyle(color: Colors.white, fontSize: 15.0),
textDirection: TextDirection.ltr,
),
));
}
return new Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: childs,
);
}
@override
Widget build(BuildContext context) {
return new ClipRRect(
borderRadius: new BorderRadius.circular(15.0),
child: new Container(
constraints: icon == null || tip == null
? new BoxConstraints(minHeight: 50.0, minWidth: 100.0)
: new BoxConstraints(minHeight: 90.0, minWidth: 120.0),
color: color,
child: bodyBuilder == null ? _buildBody() : bodyBuilder(context),
),
);
}
}
class TipDialogContainer extends StatefulWidget {
TipDialogContainer(
{Key key, @required this.child, this.duration: const Duration(seconds: 2), this.maskAlpha: 0.3}) : super(key: key);
final Widget child;
final Duration duration;
final double maskAlpha;
@override
State<StatefulWidget> createState() {
return new TipDialogContainerState();
}
}
class TipDialogContainerState extends State<TipDialogContainer>
with TickerProviderStateMixin {
Timer _timer;
bool _show;
AnimationController _animationController;
Animation _scaleAnimation;
VoidCallback _animationListener;
bool _prepareDismiss = false;
Widget _tipDialog;
bool _isAutoDismiss;
bool get isShow => _show;
void dismiss() {
setState(() {
if (_animationController.isAnimating) {
_show = false;
_animationController.stop(canceled: true);
} else {
_prepareDismiss = true;
_animationController.reverse();
}
});
}
void show({@required Widget tipDialog, bool isAutoDismiss: true}) {
assert(tipDialog != null);
_tipDialog = tipDialog;
_isAutoDismiss = isAutoDismiss;
setState(() {
_start();
_show = true;
});
}
@override
void initState() {
super.initState();
_show = false;
_animationController = new AnimationController(
value: 0.0, duration: new Duration(milliseconds: 200), vsync: this);
_animationListener = () {
if (_animationController.value == 0.0 && _prepareDismiss) {
setState(() {
_show = false;
_prepareDismiss = false;
});
}
};
_animationController.addListener(_animationListener);
_scaleAnimation =
new Tween(begin: 0.95, end: 1.0).animate(_animationController);
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
if (_show)
_start();
}
void _start() {
_animationController.forward(from: 0.0);
if (_isAutoDismiss) {
if (_timer != null) {
_timer.cancel();
if (_show) {
dismiss();
}
_timer = null;
}
_timer = new Timer(widget.duration, () {
dismiss();
_timer = null;
});
}
}
@override
void dispose() {
if (_timer != null) {
_timer.cancel();
if (_show)
dismiss();
}
_animationController.removeListener(_animationListener);
_animationController.dispose();
super.dispose();
}
Widget _buildMaskLayer() {
return new LayoutBuilder(builder: (context, size) {
return new FadeTransition(
opacity: _animationController,
child: new Container(width: size.maxWidth, height: size.maxHeight,color: Colors.black.withAlpha(widget.maskAlpha * 255 ~/ 1),
),
);
});
}
@override
Widget build(BuildContext context) {
List<Widget> widgets = [widget.child];
if (_show) {
widgets.add(_buildMaskLayer());
widgets.add(new ScaleTransition(scale: _scaleAnimation,
child: new FadeTransition(opacity: _animationController, child: _tipDialog,
),
));
}
return new _TipDialogProvider(
controller: new TipDialogController(showCallback: show, dismissCallback: dismiss),
child: new Stack(alignment: Alignment.center, children: widgets)
);
}
}
typedef void ShowTipDialogCallback({@required Widget tipDialog, bool isAutoDismiss});
typedef void DismissTipDialogCallback();
class TipDialogController {
final ShowTipDialogCallback showCallback;
final DismissTipDialogCallback dismissCallback;
TipDialogController({Key key, ShowTipDialogCallback showCallback, DismissTipDialogCallback dismissCallback})
: showCallback = showCallback,
dismissCallback = dismissCallback;
show({@required Widget tipDialog, bool isAutoDismiss: true}) {
showCallback(tipDialog: tipDialog, isAutoDismiss: isAutoDismiss);
}
dismiss() {
dismissCallback();
}
}
class _TipDialogProvider extends InheritedWidget {
final TipDialogController controller;
_TipDialogProvider({Key key, @required this.controller, @required Widget child})
: assert(controller != null), assert(child != null), super(key: key, child: child);
static TipDialogController of(BuildContext context) {
final _TipDialogProvider scope =context.inheritFromWidgetOfExactType(_TipDialogProvider);
return scope?.controller;
}
@override
bool updateShouldNotify(_TipDialogProvider oldWidget) {
return controller != oldWidget.controller;
}
}
typedef Widget TipDialogBuilder(BuildContext context, TipDialogController controller);
class TipDialogConnector extends StatelessWidget {
final TipDialogBuilder builder;
TipDialogConnector({this.builder});
@override
Widget build(BuildContext context) {
return builder(context, _TipDialogProvider.of(context));
}
}
1 comments:
Click here for commentsNo more live link in this comments field
ConversionConversion EmoticonEmoticon