Last active
December 21, 2022 02:55
-
-
Save maheshj01/e96ed09af35868c256e37f2ea3c98de7 to your computer and use it in GitHub Desktop.
Flutter Raining Balls (Flutter Counter app Challenge 2020)
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
| // Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| import 'dart:math' as math; | |
| import 'package:flutter/material.dart'; | |
| void main() => runApp(MyApp()); | |
| class MyApp extends StatelessWidget { | |
| const MyApp({super.key}); | |
| @override | |
| Widget build(BuildContext context) { | |
| return MaterialApp( | |
| title: 'Flutter Demo', | |
| debugShowCheckedModeBanner: false, | |
| theme: ThemeData( | |
| primarySwatch: Colors.blue, | |
| ), | |
| home: Counter(), | |
| ); | |
| } | |
| } | |
| class Counter extends StatefulWidget { | |
| const Counter({super.key}); | |
| @override | |
| _CounterState createState() => _CounterState(); | |
| } | |
| class _CounterState extends State<Counter> with SingleTickerProviderStateMixin { | |
| @override | |
| void dispose() { | |
| // TODO: implement dispose | |
| super.dispose(); | |
| } | |
| void _incrementCounter() { | |
| setState(() { | |
| counter++; | |
| }); | |
| } | |
| int counter = 0; | |
| late Size size; | |
| @override | |
| Widget build(BuildContext context) { | |
| // TODO: implement build | |
| size = MediaQuery.of(context).size; | |
| return Scaffold( | |
| // appBar: AppBar(), | |
| body: Stack( | |
| children: [ | |
| Align( | |
| alignment: Alignment.center, | |
| child: Container( | |
| child: Text('$counter', | |
| key: const Key('counter'), | |
| style: const TextStyle(color: Colors.black, fontSize: 30)), | |
| )), | |
| for (int i = 0; i < counter; i++) | |
| Ball( | |
| size: size, | |
| ) | |
| ], | |
| ), | |
| floatingActionButton: Row( | |
| mainAxisAlignment: MainAxisAlignment.center, | |
| children: [ | |
| const SizedBox( | |
| width: 30, | |
| ), | |
| FloatingActionButton( | |
| key: const Key('increment'), | |
| onPressed: _incrementCounter, | |
| tooltip: 'ball Animation', | |
| child: const Icon(Icons.radio_button_checked)), | |
| ], | |
| ), | |
| ); | |
| } | |
| } | |
| class Ball extends StatefulWidget { | |
| const Ball({ | |
| Key? key, | |
| required this.size, | |
| }) : super(key: key); | |
| final Size size; | |
| @override | |
| _BallState createState() => _BallState(); | |
| } | |
| class _BallState extends State<Ball> with SingleTickerProviderStateMixin { | |
| late Animation<double> _ballAnimation; | |
| late AnimationController ballController; | |
| @override | |
| void initState() { | |
| super.initState(); | |
| generateList(); | |
| ballController = AnimationController( | |
| vsync: this, | |
| duration: const Duration(milliseconds: 4000), | |
| )..addListener(() { | |
| if (ballController.status == AnimationStatus.completed) { | |
| ballController.reset(); | |
| } | |
| }); | |
| _ballAnimation = Tween<double>(begin: widget.size.height + 100, end: 10).animate( | |
| CurvedAnimation(parent: ballController, curve: GravityCurve())); | |
| final index = math.Random().nextInt(positions.length); | |
| dx = positions[index]; | |
| ballController.forward(); | |
| } | |
| @override | |
| void dispose() { | |
| ballController.dispose(); | |
| super.dispose(); | |
| } | |
| void generateList() { | |
| for (double i = -widget.size.width / 2; | |
| i < widget.size.width / 2; | |
| i += 50.0) { | |
| positions.add(i); | |
| } | |
| } | |
| Widget ball({double? size}) { | |
| return Container( | |
| height: size ?? 20, | |
| decoration: const BoxDecoration(color: Colors.red, shape: BoxShape.circle), | |
| ); | |
| } | |
| double? dx; | |
| List<double> positions = []; | |
| @override | |
| Widget build(BuildContext context) { | |
| // TODO: implement build | |
| return AnimatedBuilder( | |
| animation: _ballAnimation, | |
| builder: (context, child) { | |
| return Transform.translate( | |
| offset: Offset(dx!, _ballAnimation.value), child: ball()); | |
| }); | |
| } | |
| } | |
| class GravityCurve extends Curve { | |
| // 0-1 | |
| @override | |
| double transformInternal(double t) { | |
| return math.sin(math.pi * t); | |
| // return t < 0.5 ? sin(pi * t) : sin(3 * t * pi / 2); | |
| } | |
| } |
maheshj01
commented
Dec 21, 2020
Author

Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment