Skip to content

Instantly share code, notes, and snippets.

@mingsai
Forked from Kartik1607/main.dart
Last active December 4, 2019 21:38
Show Gist options
  • Save mingsai/cee6957a167a1433bebbecdf89480651 to your computer and use it in GitHub Desktop.
Save mingsai/cee6957a167a1433bebbecdf89480651 to your computer and use it in GitHub Desktop.
Clapping Hands
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
enum ScoreWidgetStatus {
HIDDEN,
BECOMING_VISIBLE,
VISIBLE,
BECOMING_INVISIBLE
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
int _counter = 0;
ScoreWidgetStatus _scoreWidgetStatus = ScoreWidgetStatus.HIDDEN;
final duration = new Duration(milliseconds: 300);
final oneSecond = new Duration(seconds: 1);
Timer holdTimer, scoreOutETA;
AnimationController scoreInAnimationController, scoreOutAnimationController,
scoreSizeAnimationController;
Animation scoreOutPositionAnimation;
initState() {
super.initState();
scoreInAnimationController = new AnimationController(duration: new Duration(milliseconds: 150), vsync: this);
scoreInAnimationController.addListener((){
setState(() {}); // Calls render function
});
scoreOutAnimationController = new AnimationController(vsync: this, duration: duration);
scoreOutPositionAnimation = new Tween(begin: 100.0, end: 150.0).animate(
new CurvedAnimation(parent: scoreOutAnimationController, curve: Curves.easeOut)
);
scoreOutPositionAnimation.addListener((){
setState(() {});
});
scoreOutAnimationController.addStatusListener((status) {
if (status == AnimationStatus.completed) {
_scoreWidgetStatus = ScoreWidgetStatus.HIDDEN;
}
});
scoreSizeAnimationController = new AnimationController(vsync: this, duration: new Duration(milliseconds: 150));
scoreSizeAnimationController.addStatusListener((status) {
if(status == AnimationStatus.completed) {
scoreSizeAnimationController.reverse();
}
});
scoreSizeAnimationController.addListener((){
setState(() {});
});
}
dispose() {
super.dispose();
scoreInAnimationController.dispose();
scoreOutAnimationController.dispose();
}
void increment(Timer t) {
scoreSizeAnimationController.forward(from: 0.0);
setState(() {
_counter++;
});
}
void onTapDown(TapDownDetails tap) {
// User pressed the button. This can be a tap or a hold.
if (scoreOutETA != null) {
scoreOutETA.cancel(); // We do not want the score to vanish!
}
if(_scoreWidgetStatus == ScoreWidgetStatus.BECOMING_INVISIBLE) {
// We tapped down while the widget was flying up. Need to cancel that animation.
scoreOutAnimationController.stop(canceled: true);
_scoreWidgetStatus = ScoreWidgetStatus.VISIBLE;
}
else if (_scoreWidgetStatus == ScoreWidgetStatus.HIDDEN ) {
_scoreWidgetStatus = ScoreWidgetStatus.BECOMING_VISIBLE;
scoreInAnimationController.forward(from: 0.0);
}
increment(null); // Take care of tap
holdTimer = new Timer.periodic(duration, increment); // Takes care of hold
}
void onTapUp(TapUpDetails tap) {
// User removed his finger from button.
scoreOutETA = new Timer(oneSecond, () {
scoreOutAnimationController.forward(from: 0.0);
_scoreWidgetStatus = ScoreWidgetStatus.BECOMING_INVISIBLE;
});
holdTimer.cancel();
}
Widget getScoreButton() {
var scorePosition = 0.0;
var scoreOpacity = 0.0;
var extraSize = 0.0;
switch(_scoreWidgetStatus) {
case ScoreWidgetStatus.HIDDEN:
break;
case ScoreWidgetStatus.BECOMING_VISIBLE :
case ScoreWidgetStatus.VISIBLE:
scorePosition = scoreInAnimationController.value * 100;
scoreOpacity = scoreInAnimationController.value;
extraSize = scoreSizeAnimationController.value * 10;
break;
case ScoreWidgetStatus.BECOMING_INVISIBLE:
scorePosition = scoreOutPositionAnimation.value;
scoreOpacity = 1.0 - scoreOutAnimationController.value;
}
return new Positioned(
child: new Opacity(opacity: scoreOpacity, child: new Container(
height: 50.0 + extraSize,
width: 50.0 + extraSize,
decoration: new ShapeDecoration(
shape: new CircleBorder(
side: BorderSide.none
),
color: Colors.pink,
),
child: new Center(child:
new Text("+" + _counter.toString(),
style: new TextStyle(color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 15.0),))
)),
bottom: scorePosition
);
}
Widget getClapButton() {
// Using custom gesture detector because we want to keep increasing the claps
// when user holds the button.
var extraSize = 0.0;
if (_scoreWidgetStatus == ScoreWidgetStatus.VISIBLE || _scoreWidgetStatus == ScoreWidgetStatus.BECOMING_VISIBLE) {
extraSize = scoreSizeAnimationController.value * 10;
}
return new GestureDetector(
onTapUp: onTapUp,
onTapDown: onTapDown,
child: new Container(
height: 60.0 + extraSize ,
width: 60.0 + extraSize,
padding: new EdgeInsets.all(10.0),
decoration: new BoxDecoration(
border: new Border.all(color: Colors.pink, width: 1.0),
borderRadius: new BorderRadius.circular(50.0),
color: Colors.white,
boxShadow: [
new BoxShadow(color: Colors.pink, blurRadius: 8.0)
]
),
child: new ImageIcon(
new AssetImage("images/clap.png"), color: Colors.pink,
size: 40.0),
)
);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
'You have pushed the button this many times:',
),
new Text(
'$_counter',
style: Theme
.of(context)
.textTheme
.display1,
),
],
),
),
floatingActionButton: new Padding(
padding: new EdgeInsets.only(right: 20.0),
child: new Stack(
alignment: FractionalOffset.center,
overflow: Overflow.visible,
children: <Widget>[
getScoreButton(),
getClapButton(),
],
)
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment