Instantly share code, notes, and snippets.
Forked from flippingbitss/PlayButtonFinalApp.dart
Created
May 31, 2022 20:15
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save hermanho/e39c8a827ba42dcf765093b82a745e23 to your computer and use it in GitHub Desktop.
This file contains 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' show pi; | |
void main() { | |
runApp(MyApp()); | |
} | |
class MyApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: Color.fromARGB(255, 18, 32, 47)), | |
debugShowCheckedModeBanner: false, | |
home: Scaffold( | |
body: Center( | |
child: SizedBox( | |
height: 200, | |
width: 200, | |
child: PlayButton( | |
pauseIcon: Icon(Icons.pause, color: Colors.black, size: 90), | |
playIcon: Icon(Icons.play_arrow, color: Colors.black, size: 90), | |
onPressed: () {}, | |
), | |
), | |
), | |
), | |
); | |
} | |
} | |
class PlayButton extends StatefulWidget { | |
final bool initialIsPlaying; | |
final Icon playIcon; | |
final Icon pauseIcon; | |
final VoidCallback onPressed; | |
PlayButton({ | |
@required this.onPressed, | |
this.initialIsPlaying = false, | |
this.playIcon = const Icon(Icons.play_arrow), | |
this.pauseIcon = const Icon(Icons.pause), | |
}) : assert(onPressed != null); | |
@override | |
_PlayButtonState createState() => _PlayButtonState(); | |
} | |
class _PlayButtonState extends State<PlayButton> with TickerProviderStateMixin { | |
static const _kToggleDuration = Duration(milliseconds: 300); | |
static const _kRotationDuration = Duration(seconds: 5); | |
bool isPlaying; | |
// rotation and scale animations | |
AnimationController _rotationController; | |
AnimationController _scaleController; | |
double _rotation = 0; | |
double _scale = 0.85; | |
bool get _showWaves => !_scaleController.isDismissed; | |
void _updateRotation() => _rotation = _rotationController.value * 2 * pi; | |
void _updateScale() => _scale = (_scaleController.value * 0.2) + 0.85; | |
@override | |
void initState() { | |
isPlaying = widget.initialIsPlaying; | |
_rotationController = | |
AnimationController(vsync: this, duration: _kRotationDuration) | |
..addListener(() => setState(_updateRotation)) | |
..repeat(); | |
_scaleController = | |
AnimationController(vsync: this, duration: _kToggleDuration) | |
..addListener(() => setState(_updateScale)); | |
super.initState(); | |
} | |
void _onToggle() { | |
setState(() => isPlaying = !isPlaying); | |
if (_scaleController.isCompleted) { | |
_scaleController.reverse(); | |
} else { | |
_scaleController.forward(); | |
} | |
widget.onPressed(); | |
} | |
Widget _buildIcon(bool isPlaying) { | |
return SizedBox.expand( | |
key: ValueKey<bool>(isPlaying), | |
child: IconButton( | |
icon: isPlaying ? widget.pauseIcon : widget.playIcon, | |
onPressed: _onToggle, | |
), | |
); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return ConstrainedBox( | |
constraints: BoxConstraints(minWidth: 48, minHeight: 48), | |
child: Stack( | |
alignment: Alignment.center, | |
children: [ | |
if (_showWaves) ...[ | |
Blob(color: Color(0xff0092ff), scale: _scale, rotation: _rotation), | |
Blob(color: Color(0xff4ac7b7), scale: _scale, rotation: _rotation * 2 - 30), | |
Blob(color: Color(0xffa4a6f6), scale: _scale, rotation: _rotation * 3 - 45), | |
], | |
Container( | |
constraints: BoxConstraints.expand(), | |
child: AnimatedSwitcher( | |
child: _buildIcon(isPlaying), | |
duration: _kToggleDuration, | |
), | |
decoration: BoxDecoration( | |
shape: BoxShape.circle, | |
color: Colors.white, | |
), | |
), | |
], | |
), | |
); | |
} | |
@override | |
void dispose() { | |
_scaleController.dispose(); | |
_rotationController.dispose(); | |
super.dispose(); | |
} | |
} | |
class Blob extends StatelessWidget { | |
final double rotation; | |
final double scale; | |
final Color color; | |
const Blob({this.color, this.rotation = 0, this.scale = 1}); | |
@override | |
Widget build(BuildContext context) { | |
return Transform.scale( | |
scale: scale, | |
child: Transform.rotate( | |
angle: rotation, | |
child: Container( | |
decoration: BoxDecoration( | |
color: color, | |
borderRadius: BorderRadius.only( | |
topLeft: Radius.circular(150), | |
topRight: Radius.circular(240), | |
bottomLeft: Radius.circular(220), | |
bottomRight: Radius.circular(180), | |
), | |
), | |
), | |
), | |
); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment