Skip to content

Commit e1a4b1f

Browse files
Merge pull request #237 from deepikahr/master
gftoast completed
2 parents 756b567 + 7411e72 commit e1a4b1f

File tree

4 files changed

+220
-154
lines changed

4 files changed

+220
-154
lines changed

lib/components/badge/gf_icon_badge.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ class GFIconBadge extends StatefulWidget {
2929
_GFIconBadgeState createState() => _GFIconBadgeState();
3030
}
3131

32-
33-
3432
class _GFIconBadgeState extends State<GFIconBadge> {
3533
@override
3634
Widget build(BuildContext context) => Container(

lib/components/toast/gf_toast.dart

Lines changed: 189 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -1,177 +1,214 @@
11
import 'dart:async';
2+
23
import 'package:flutter/material.dart';
34
import 'package:flutter/widgets.dart';
4-
import 'package:getwidget/getwidget.dart';
5-
6-
class GFToast extends StatefulWidget {
7-
///Creates [GFToast] that can be used to display quick warning or error messages.
8-
/// Toast has to be wrap inside the body like [GFFloatingWidget]. See [GFFloatingWidget]
9-
const GFToast({
10-
Key? key,
11-
this.child,
12-
this.button,
13-
this.backgroundColor,
14-
this.text,
15-
this.width,
16-
this.type = GFToastType.basic,
17-
this.autoDismiss = true,
18-
this.alignment,
19-
this.animationDuration = const Duration(milliseconds: 300),
20-
this.duration = const Duration(milliseconds: 300),
21-
this.textStyle = const TextStyle(color: Colors.white70),
22-
this.autoDismissDuration = const Duration(milliseconds: 3000),
23-
}) : super(key: key);
24-
25-
/// child of type [Widget]is alternative to text key. text will get priority over child
26-
final Widget? child;
27-
28-
/// button of type [Widget],or you can use [GFButton] for easy implementation with [GFToast]
29-
final Widget? button;
30-
31-
///pass color of type [Color] or [GFColors] for background of [GFToast]
32-
final Color? backgroundColor;
33-
34-
/// text of type [String] is alternative to child. text will get priority over child
35-
final String? text;
36-
37-
/// textStyle of type [textStyle] will be applicable to text only and not for the child
38-
final TextStyle textStyle;
39-
40-
/// width of type [double] used to control the width of the [GFToast]
41-
final double? width;
42-
43-
///type of [GFToastType] which takes the type ie, basic, rounded and fullWidth for the [GFToast]
44-
final GFToastType type;
45-
46-
///type of [bool] which takes bool values ie, true or false to automatically hide the [GFToast] message
47-
final bool autoDismiss;
48-
49-
///type of [Duration] which takes the duration of the fade in animation
50-
final Duration animationDuration;
51-
52-
///type of [Duration] which takes the duration of the animation
53-
final Duration duration;
5+
import 'package:getwidget/position/gf_toast_position.dart';
6+
7+
class GFToast {
8+
/// text of type [String] display on toast
9+
String? text;
10+
11+
/// defines the duration of time toast display over screen
12+
int? toastDuration;
13+
14+
/// defines the position of toast over the screen
15+
GFToastPosition? toastPosition;
16+
17+
/// defines the background color of the toast
18+
Color? backgroundColor;
19+
20+
/// defines the test style of the toast text
21+
TextStyle? textStyle;
22+
23+
/// defines the border radius of the toast
24+
double? toastBorderRadius;
25+
26+
/// defines the border of the toast
27+
Border? border;
28+
29+
/// defines the trailing widget of the toast
30+
late Widget trailing;
31+
32+
// ignore: type_annotate_public_apis, always_declare_return_types
33+
static showToast(
34+
text,
35+
BuildContext context, {
36+
toastDuration,
37+
toastPosition,
38+
backgroundColor = const Color(0xAA000000),
39+
textStyle = const TextStyle(fontSize: 15, color: Colors.white),
40+
toastBorderRadius = 20.0,
41+
border,
42+
trailing,
43+
}) {
44+
assert(text != null);
45+
ToastView.dismiss();
46+
ToastView.createView(text, context, toastDuration, toastPosition,
47+
backgroundColor, textStyle, toastBorderRadius, border, trailing);
48+
}
49+
}
50+
51+
class ToastView {
52+
static final ToastView _instance = ToastView._internal();
53+
// ignore: sort_constructors_first
54+
factory ToastView() => _instance;
55+
// ignore: sort_constructors_first
56+
ToastView._internal();
57+
58+
static OverlayState? overlayState;
59+
static OverlayEntry? _overlayEntry;
60+
static bool _isVisible = false;
61+
62+
// ignore: avoid_void_async
63+
static void createView(
64+
String text,
65+
BuildContext context,
66+
int? toastDuration,
67+
GFToastPosition? toastPosition,
68+
Color backgroundColor,
69+
TextStyle textStyle,
70+
double toastBorderRadius,
71+
Border? border,
72+
// ignore: type_annotate_public_apis
73+
trailing) async {
74+
overlayState = Overlay.of(context, rootOverlay: false);
75+
76+
final Widget toastChild = ToastCard(
77+
Container(
78+
decoration: BoxDecoration(
79+
color: backgroundColor,
80+
borderRadius: BorderRadius.circular(toastBorderRadius),
81+
border: border,
82+
),
83+
margin: const EdgeInsets.symmetric(horizontal: 16),
84+
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
85+
child: trailing == null
86+
? Text(text, softWrap: true, style: textStyle)
87+
: Row(
88+
mainAxisAlignment: MainAxisAlignment.spaceBetween,
89+
children: [
90+
Expanded(
91+
child: Text(text, style: textStyle),
92+
),
93+
const SizedBox(
94+
width: 6,
95+
),
96+
trailing
97+
],
98+
),
99+
),
100+
Duration(seconds: toastDuration ?? 2),
101+
fadeDuration: 500);
102+
103+
_overlayEntry = OverlayEntry(
104+
builder: (BuildContext context) =>
105+
_showWidgetBasedOnPosition(toastChild, toastPosition));
106+
107+
_isVisible = true;
108+
overlayState!.insert(_overlayEntry!);
109+
await Future.delayed(Duration(seconds: toastDuration ?? 2));
110+
await dismiss();
111+
}
54112

55-
///type of [Duration] which takes the duration of the autoDismiss
56-
final Duration autoDismissDuration;
113+
static Positioned _showWidgetBasedOnPosition(
114+
Widget child, GFToastPosition? toastPosition) {
115+
switch (toastPosition) {
116+
case GFToastPosition.BOTTOM:
117+
return Positioned(bottom: 60, left: 18, right: 18, child: child);
118+
case GFToastPosition.BOTTOM_LEFT:
119+
return Positioned(bottom: 60, left: 18, child: child);
120+
case GFToastPosition.BOTTOM_RIGHT:
121+
return Positioned(bottom: 60, right: 18, child: child);
122+
case GFToastPosition.CENTER:
123+
return Positioned(
124+
top: 60, bottom: 60, left: 18, right: 18, child: child);
125+
case GFToastPosition.CENTER_LEFT:
126+
return Positioned(top: 60, bottom: 60, left: 18, child: child);
127+
case GFToastPosition.CENTER_RIGHT:
128+
return Positioned(top: 60, bottom: 60, right: 18, child: child);
129+
case GFToastPosition.TOP_LEFT:
130+
return Positioned(top: 110, left: 18, child: child);
131+
case GFToastPosition.TOP_RIGHT:
132+
return Positioned(top: 110, right: 18, child: child);
133+
default:
134+
return Positioned(top: 110, left: 18, right: 18, child: child);
135+
}
136+
}
137+
138+
static Future<void> dismiss() async {
139+
if (!_isVisible) {
140+
return;
141+
}
142+
_isVisible = false;
143+
_overlayEntry?.remove();
144+
}
145+
}
57146

58-
/// type of [Alignment] used to align the text inside the toast
59-
final Alignment? alignment;
147+
class ToastCard extends StatefulWidget {
148+
const ToastCard(this.child, this.duration,
149+
{Key? key, this.fadeDuration = 500})
150+
: super(key: key);
151+
152+
final Widget child;
153+
final Duration duration;
154+
final int fadeDuration;
60155

61156
@override
62-
_GFToastState createState() => _GFToastState();
157+
ToastStateFulState createState() => ToastStateFulState();
63158
}
64159

65-
class _GFToastState extends State<GFToast> with TickerProviderStateMixin {
66-
late AnimationController animationController, fadeAnimationController;
67-
late Animation<double> animation, fadeAnimation;
68-
Timer? timer;
69-
bool hideToast = false;
160+
class ToastStateFulState extends State<ToastCard>
161+
with SingleTickerProviderStateMixin {
162+
void showAnimation() {
163+
_animationController!.forward();
164+
}
165+
166+
void hideAnimation() {
167+
_animationController!.reverse();
168+
_timer?.cancel();
169+
}
170+
171+
AnimationController? _animationController;
172+
late Animation _fadeAnimation;
173+
174+
Timer? _timer;
70175

71176
@override
72177
void initState() {
73-
animationController =
74-
AnimationController(duration: widget.duration, vsync: this);
75-
animation = CurvedAnimation(
76-
parent: animationController,
77-
curve: Curves.easeIn,
178+
_animationController = AnimationController(
179+
vsync: this,
180+
duration: Duration(milliseconds: widget.fadeDuration),
78181
);
182+
_fadeAnimation =
183+
CurvedAnimation(parent: _animationController!, curve: Curves.easeIn);
184+
super.initState();
79185

80-
if (mounted) {
81-
animationController.forward();
82-
fadeAnimationController =
83-
AnimationController(duration: widget.animationDuration, vsync: this)
84-
..addListener(() => setState(() {}));
85-
fadeAnimation = Tween<double>(
86-
begin: 0,
87-
end: 1,
88-
).animate(fadeAnimationController);
89-
timer = Timer(widget.duration, () {
90-
if (mounted) {
91-
fadeAnimationController.forward();
92-
}
93-
});
94-
fadeAnimation = Tween<double>(
95-
begin: 1,
96-
end: 0,
97-
).animate(fadeAnimationController);
98-
fadeAnimation.addStatusListener((AnimationStatus state) {
99-
if (fadeAnimation.isCompleted && widget.autoDismiss) {
100-
setState(() {
101-
hideToast = true;
102-
});
103-
}
104-
});
105-
}
186+
showAnimation();
187+
_timer = Timer(widget.duration, hideAnimation);
188+
}
106189

107-
super.initState();
190+
@override
191+
void deactivate() {
192+
_timer?.cancel();
193+
_animationController!.stop();
194+
super.deactivate();
108195
}
109196

110197
@override
111198
void dispose() {
112-
animationController.dispose();
113-
fadeAnimationController.dispose();
114-
timer?.cancel();
199+
_timer?.cancel();
200+
_animationController?.dispose();
115201
super.dispose();
116202
}
117203

118204
@override
119-
Widget build(BuildContext context) => hideToast
120-
? Container()
121-
: FadeTransition(
122-
opacity: widget.autoDismiss ? fadeAnimation : animation,
123-
child: Column(
124-
children: <Widget>[
125-
Container(
126-
width: widget.type == GFToastType.fullWidth
127-
? MediaQuery.of(context).size.width
128-
: widget.width ?? MediaQuery.of(context).size.width * 0.885,
129-
constraints: const BoxConstraints(minHeight: 50),
130-
margin: widget.type == GFToastType.fullWidth
131-
? const EdgeInsets.only(left: 0, right: 0)
132-
: const EdgeInsets.only(left: 10, right: 10),
133-
padding: const EdgeInsets.all(10),
134-
decoration: BoxDecoration(
135-
borderRadius: widget.type == GFToastType.basic
136-
? BorderRadius.circular(0)
137-
: widget.type == GFToastType.rounded
138-
? BorderRadius.circular(10)
139-
: BorderRadius.zero,
140-
color: widget.backgroundColor ?? const Color(0xff323232),
141-
boxShadow: [
142-
BoxShadow(
143-
color: Colors.black.withOpacity(0.40),
144-
blurRadius: 6,
145-
)
146-
]),
147-
child: Row(
148-
children: <Widget>[
149-
Flexible(
150-
flex: 7,
151-
fit: FlexFit.tight,
152-
child: Align(
153-
alignment: widget.alignment ?? Alignment.topLeft,
154-
child: widget.text != null
155-
? Text(widget.text!, style: widget.textStyle)
156-
: (widget.child ?? Container()),
157-
),
158-
),
159-
const SizedBox(
160-
width: 10,
161-
),
162-
widget.button != null
163-
? Flexible(
164-
flex: 4,
165-
fit: FlexFit.tight,
166-
child: Align(
167-
alignment: Alignment.topRight,
168-
child: widget.button,
169-
))
170-
: Container()
171-
],
172-
),
173-
),
174-
],
205+
Widget build(BuildContext context) => FadeTransition(
206+
opacity: _fadeAnimation as Animation<double>,
207+
child: Center(
208+
child: Material(
209+
color: Colors.transparent,
210+
child: widget.child,
175211
),
176-
);
212+
),
213+
);
177214
}

lib/getwidget.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export 'colors/gf_color.dart';
5151
export 'direction/gf_shimmer_direction.dart';
5252
export 'position/gf_badge_position.dart';
5353
export 'position/gf_position.dart';
54+
export 'position/gf_toast_position.dart';
5455
export 'shape/gf_avatar_shape.dart';
5556
export 'shape/gf_badge_shape.dart';
5657
export 'shape/gf_button_shape.dart';

0 commit comments

Comments
 (0)