Skip to content

Commit 8c45c95

Browse files
author
Vivek Chib
committed
fixed animation restart when changing time value
1 parent 17f29d1 commit 8c45c95

File tree

5 files changed

+141
-132
lines changed

5 files changed

+141
-132
lines changed

lib/main.dart

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,24 @@ class MyApp extends StatelessWidget {
3636
Widget build(BuildContext context) {
3737
final theme = MaterialTheme(Theme.of(context).textTheme);
3838

39-
return Consumer<ThemeProvider>(builder: (context, themeProvider, child) {
40-
return MaterialApp(
41-
title: 'Flutter Curve Visualizer',
42-
debugShowCheckedModeBanner: false,
43-
themeMode: themeProvider.getThemeMode(),
44-
theme: theme.lightMediumContrast(),
45-
darkTheme: theme.dark(),
46-
home: LayoutBuilder(
47-
builder: (context, constraints) {
48-
return ScreenModeWidget(
49-
mode: getLayoutType(constraints.maxWidth),
50-
child: const HomePage(),
51-
);
52-
},
53-
),
54-
);
55-
});
39+
return Consumer<ThemeProvider>(
40+
builder: (context, themeProvider, child) {
41+
return MaterialApp(
42+
title: 'Flutter Curve Visualizer',
43+
debugShowCheckedModeBanner: false,
44+
themeMode: themeProvider.getThemeMode(),
45+
theme: theme.lightMediumContrast(),
46+
darkTheme: theme.dark(),
47+
home: LayoutBuilder(
48+
builder: (context, constraints) {
49+
return ScreenModeWidget(
50+
mode: getLayoutType(constraints.maxWidth),
51+
child: const HomePage(),
52+
);
53+
},
54+
),
55+
);
56+
},
57+
);
5658
}
5759
}

lib/utils/curves_enum.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ enum CurvesEnum {
4444
elasticIn(Curves.elasticIn),
4545
elasticOut(Curves.elasticOut),
4646
elasticInOut(Curves.elasticInOut),
47-
custom(Cubic(0.77, 0.0, 0.175, 1.0));
47+
custom(Cubic(0.48, 1.26, 0.41, 0.6));
4848

4949
final Curve curve;
5050

lib/views/home_page.dart

Lines changed: 64 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,10 @@ import 'package:flutter/material.dart';
22
import 'package:flutter_curve_visualizer/screen_mode.dart';
33
import 'package:flutter_curve_visualizer/utils/curves_enum.dart';
44
import 'package:flutter_curve_visualizer/utils/extension/string.dart';
5-
import 'package:flutter_curve_visualizer/utils/theme/theme_provider.dart';
65
import 'package:flutter_curve_visualizer/views/widgets/animated_box/animated_box_widget.dart';
6+
import 'package:flutter_curve_visualizer/views/widgets/appbar.dart';
77
import 'package:flutter_curve_visualizer/views/widgets/dropdown_menu.dart';
88
import 'package:flutter_curve_visualizer/views/widgets/graph/graph_widget.dart';
9-
import 'package:flutter_svg/flutter_svg.dart';
10-
import 'package:provider/provider.dart';
11-
import 'package:url_launcher/url_launcher.dart';
12-
139
import 'widgets/code_block.dart';
1410

1511
class HomePage extends StatefulWidget {
@@ -20,20 +16,15 @@ class HomePage extends StatefulWidget {
2016
}
2117

2218
class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
19+
late AnimationController playPauseController;
2320
late AnimationController controller;
24-
25-
late CurvedAnimation animation;
21+
late CurvedAnimation curveAnimation;
2622

2723
late String selectedCategory;
28-
2924
late CurvesEnum selectedCurve;
3025

3126
late int animationTime;
3227

33-
late AnimationController playPauseController;
34-
35-
bool showCurveOutline = true;
36-
3728
@override
3829
void initState() {
3930
super.initState();
@@ -45,44 +36,33 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
4536
playPauseController = AnimationController(
4637
vsync: this,
4738
duration: Duration(milliseconds: 250),
48-
);
39+
)..forward();
4940

5041
controller = AnimationController(
5142
vsync: this,
5243
duration: Duration(seconds: animationTime),
53-
);
44+
)..repeat(reverse: true);
5445

55-
animation = CurvedAnimation(
46+
curveAnimation = CurvedAnimation(
5647
parent: controller,
5748
curve: selectedCurve.curve,
5849
);
59-
60-
controller.repeat(reverse: true);
61-
62-
controller.addListener(playPauseListener);
63-
}
64-
65-
void playPauseListener() {
66-
if (controller.isAnimating) {
67-
playPauseController.forward();
68-
} else {
69-
playPauseController.reset();
70-
}
7150
}
7251

7352
@override
7453
void dispose() {
75-
controller.removeListener(playPauseListener);
7654
playPauseController.dispose();
7755
controller.dispose();
7856
super.dispose();
7957
}
8058

8159
void updateCategory(String? category) {
60+
if (category == null) return;
61+
8262
setState(() {
83-
selectedCategory = category!;
63+
selectedCategory = category;
8464
selectedCurve = CurvesEnum.list[category]!.first;
85-
animation = CurvedAnimation(
65+
curveAnimation = CurvedAnimation(
8666
parent: controller,
8767
curve: selectedCurve.curve,
8868
);
@@ -92,55 +72,66 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
9272
void updateCurve(CurvesEnum curve) {
9373
setState(() {
9474
selectedCurve = curve;
95-
96-
animation = CurvedAnimation(
97-
parent: controller,
98-
curve: selectedCurve.curve,
99-
);
75+
curveAnimation.curve = curve.curve;
10076
});
10177
}
10278

10379
void updateAnimationTime(double seconds) {
104-
animationTime = seconds.toInt();
105-
controller = AnimationController(
106-
vsync: this,
107-
duration: Duration(seconds: animationTime),
108-
);
109-
setState(() {});
80+
// return if both values are same
81+
if (animationTime == seconds.toInt()) return;
11082

111-
animation = CurvedAnimation(
112-
parent: controller,
113-
curve: selectedCurve.curve,
114-
);
115-
controller.repeat(reverse: true);
116-
playPauseController.forward();
83+
setState(() {
84+
animationTime = seconds.toInt();
85+
86+
controller.duration = Duration(seconds: animationTime);
87+
88+
curveAnimation.curve = selectedCurve.curve;
89+
90+
if (controller.isForwardOrCompleted) {
91+
controller.repeat(reverse: true);
92+
} else {
93+
controller.reverse().then((value) => controller.repeat(reverse: true));
94+
}
95+
96+
playPauseController.forward();
97+
});
98+
}
99+
100+
void playPauseAnimation() {
101+
if (controller.isAnimating) {
102+
controller.stop();
103+
playPauseController.animateBack(0.0);
104+
} else {
105+
controller.repeat(reverse: true);
106+
playPauseController.forward();
107+
}
117108
}
118109

119110
@override
120111
Widget build(BuildContext context) {
121112
final screenMode = ScreenModeWidget.of(context);
122113

123-
final theme = Theme.of(context);
124-
125-
final decoration = BoxDecoration(
126-
color: Theme.of(context).colorScheme.onPrimaryFixed,
127-
borderRadius: BorderRadius.circular(10),
128-
);
114+
final double spacing = switch (screenMode) {
115+
ScreenMode.mobile => 20,
116+
ScreenMode.tablet => 30,
117+
ScreenMode.web => 30,
118+
};
129119

130120
final animationWidget = Column(
131121
children: [
132122
// Graph
133123
GraphWidget(
134-
showCurveOutline: showCurveOutline,
135124
controller: controller,
136-
animation: animation,
125+
animation: curveAnimation,
137126
),
127+
128+
// Box Animations
138129
SizedBox(
139130
width: MediaQuery.of(context).size.width /
140131
(screenMode.isMobileOrTablet ? 1 : 3),
141132
child: Wrap(
142-
spacing: 8.0,
143-
runSpacing: 8.0,
133+
spacing: spacing / 2,
134+
runSpacing: spacing / 2,
144135
runAlignment: WrapAlignment.center,
145136
alignment: WrapAlignment.center,
146137
children: AnimationType.values.map(
@@ -154,7 +145,7 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
154145
dimension: 100,
155146
child: AnimatedBoxWidget(
156147
animationType: animationType,
157-
animation: animation,
148+
animation: curveAnimation,
158149
),
159150
),
160151
],
@@ -172,22 +163,22 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
172163
),
173164
child: Column(
174165
mainAxisSize: MainAxisSize.min,
175-
spacing: 20,
166+
spacing: spacing,
176167
children: [
177168
// Code block
178169
CodeBlock(curve: selectedCurve),
179170

180171
// Curve category
181172
DropdownMenuWidget<String>(
182-
title: "Curve Category",
173+
title: "Category",
183174
value: selectedCategory,
184175
items: CurvesEnum.list.keys.toList(),
185176
onChanged: updateCategory,
186177
),
187178

188179
// Curve type
189180
DropdownMenuWidget<CurvesEnum>(
190-
title: "Curve Type",
181+
title: "Type",
191182
value: selectedCurve,
192183
items: CurvesEnum.list[selectedCategory]!..toList(),
193184
onChanged: (value) => updateCurve(value!),
@@ -199,7 +190,10 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
199190
// Curve type
200191
Container(
201192
padding: EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
202-
decoration: decoration,
193+
decoration: BoxDecoration(
194+
color: Theme.of(context).colorScheme.onPrimaryFixed,
195+
borderRadius: BorderRadius.circular(10),
196+
),
203197
child: Column(
204198
crossAxisAlignment: CrossAxisAlignment.start,
205199
children: [
@@ -221,59 +215,16 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
221215
);
222216

223217
return Scaffold(
224-
appBar: AppBar(
225-
title: const Text('Flutter Curve Visualizer'),
226-
actions: [
227-
Padding(
228-
padding: const EdgeInsets.only(right: 12.0),
229-
child: IconButton(
230-
onPressed: () {
231-
launchUrl(Uri.parse(
232-
"https://github.com/vchib1/flutter-curve-visualizer"));
233-
},
234-
icon: SvgPicture.asset(
235-
"assets/svg/github.svg",
236-
width: theme.iconTheme.size ?? 24,
237-
height: theme.iconTheme.size ?? 24,
238-
colorFilter: ColorFilter.mode(
239-
theme.iconTheme.color ?? Colors.black,
240-
BlendMode.srcIn,
241-
),
242-
),
243-
),
244-
),
245-
Padding(
246-
padding: const EdgeInsets.only(right: 12.0),
247-
child: Consumer<ThemeProvider>(
248-
builder: (context, value, child) {
249-
final iconData = value.getThemeMode() == ThemeMode.dark
250-
? Icons.light_mode
251-
: Icons.dark_mode;
252-
253-
return IconButton(
254-
onPressed: () => value.toggleTheme(),
255-
icon: Icon(iconData),
256-
);
257-
},
258-
),
259-
),
260-
],
261-
),
218+
appBar: HomeAppBar(),
262219
floatingActionButton: FloatingActionButton(
220+
onPressed: playPauseAnimation,
263221
child: Padding(
264222
padding: const EdgeInsets.all(8.0),
265223
child: AnimatedIcon(
266-
icon: AnimatedIcons.play_pause, progress: playPauseController),
224+
icon: AnimatedIcons.play_pause,
225+
progress: playPauseController,
226+
),
267227
),
268-
onPressed: () {
269-
if (controller.isAnimating) {
270-
controller.stop();
271-
playPauseController.animateBack(0.0);
272-
} else {
273-
controller.repeat(reverse: true);
274-
playPauseController.forward();
275-
}
276-
},
277228
),
278229
body: SingleChildScrollView(
279230
child: Container(
@@ -282,23 +233,23 @@ class _HomePageState extends State<HomePage> with TickerProviderStateMixin {
282233
padding: const EdgeInsets.symmetric(horizontal: 16.0),
283234
child: switch (ScreenModeWidget.of(context)) {
284235
ScreenMode.mobile => Column(
285-
spacing: 10,
236+
spacing: spacing,
286237
children: [
287238
animationWidget,
288239
controlsWidget,
289240
const SizedBox(height: 10),
290241
],
291242
),
292243
ScreenMode.tablet => Column(
293-
spacing: 20,
244+
spacing: spacing,
294245
children: [
295246
animationWidget,
296247
controlsWidget,
297248
const SizedBox(height: 20),
298249
],
299250
),
300251
ScreenMode.web => Row(
301-
spacing: 10,
252+
spacing: spacing,
302253
children: [
303254
Expanded(
304255
flex: 1,

0 commit comments

Comments
 (0)