Last active
January 9, 2020 06:02
-
-
Save tarek360/e7021a6b1077e0387c05d9bf5a0b59e5 to your computer and use it in GitHub Desktop.
Spinner Demo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
import 'dart:math'; | |
void main() { | |
runApp(SpinnerDemo()); | |
} | |
class SpinnerDemo extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
debugShowCheckedModeBanner: false, | |
darkTheme: ThemeData.dark(), | |
theme: ThemeData(brightness: Brightness.dark), | |
home: Spinner(), | |
); | |
} | |
} | |
class Spinner extends StatefulWidget { | |
final Duration loopLength; | |
Spinner({ | |
Key key, | |
this.loopLength = const Duration(milliseconds: 3500), | |
}) : super(key: key); | |
@override | |
_SpinnerState createState() => _SpinnerState(); | |
} | |
class _SpinnerState extends State<Spinner> with SingleTickerProviderStateMixin { | |
AnimationController controller; | |
@override | |
Widget build(BuildContext context) { | |
return SizedBox( | |
width: 60, | |
height: 60, | |
child: AnimatedBuilder( | |
animation: controller, | |
builder: (context, child) => CustomPaint( | |
painter: RingOfCirclesPainter(controller.value), | |
child: child, | |
), | |
child: Center(), | |
), | |
); | |
} | |
@override | |
void didUpdateWidget(Spinner oldWidget) { | |
if (widget.loopLength != oldWidget.loopLength) { | |
controller.duration = widget.loopLength; | |
} | |
super.didUpdateWidget(oldWidget); | |
} | |
@override | |
void dispose() { | |
controller.dispose(); | |
super.dispose(); | |
} | |
@override | |
void initState() { | |
super.initState(); | |
controller = AnimationController(duration: widget.loopLength, vsync: this); | |
controller.repeat(); | |
} | |
} | |
class RingOfCirclesPainter extends CustomPainter { | |
final int n = 5; | |
final double t; | |
RingOfCirclesPainter(this.t); | |
double _ringRadius; | |
double _waveRadius; | |
double _ballRadius; | |
double _gap; | |
@override | |
void paint(Canvas canvas, Size size) { | |
_ringRadius = min(size.width, size.height) * 0.35; | |
_waveRadius = min(size.width, size.height) * 0.10; | |
_ballRadius = _waveRadius * 0.7; | |
_gap = _ballRadius / 2; | |
canvas.save(); | |
canvas.translate(size.width / 2, size.height / 2); | |
for (var i = 0; i < n; i++) { | |
drawCircle(canvas, i, false); | |
} | |
for (var i = 0; i < n; i++) { | |
drawCircle(canvas, i, true); | |
} | |
canvas.restore(); | |
} | |
@override | |
bool shouldRepaint(RingOfCirclesPainter oldDelegate) => n != oldDelegate.n || t != oldDelegate.t; | |
void drawCircle(Canvas canvas, int i, bool above) { | |
final color = circlesColor[i]; | |
var angle0 = (i / n - t) % 1 * (2 * pi); | |
var angle1 = angle0 - t * (2 * pi); | |
if (cos(angle1) < 0 == above) { | |
return; | |
} | |
canvas.save(); | |
canvas.rotate(angle0); | |
canvas.translate((_ringRadius + sin(angle1) * _waveRadius), 0); | |
var paint = Paint()..strokeWidth = (_gap * 2); | |
paint | |
..style = PaintingStyle.fill | |
..color = color; | |
canvas.drawCircle(Offset.zero, _ballRadius, paint); | |
canvas.restore(); | |
} | |
} | |
const circlesColor = [AppColors.red, AppColors.amber, AppColors.green, AppColors.purple, AppColors.blue]; | |
class AppColors { | |
static const red = Color(0xFFED2224); | |
static const amber = Color(0xFFF69E1D); | |
static const green = Color(0xFF19AC5B); | |
static const purple = Color(0xFF8150A0); | |
static const blue = Color(0xFF347FC2); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment