diff --git a/CHANGELOG.md b/CHANGELOG.md index ac07159..0c9a77e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,3 @@ -## [0.0.1] - TODO: Add release date. +## [0.1.0] -* TODO: Describe initial release. +* Initial Open Source release. diff --git a/lib/miniplayer.dart b/lib/miniplayer.dart index 139d16a..e30023a 100644 --- a/lib/miniplayer.dart +++ b/lib/miniplayer.dart @@ -1,7 +1,145 @@ library miniplayer; -/// A Calculator. -class Calculator { - /// Returns [value] plus 1. - int addOne(int value) => value + 1; +import 'dart:async'; + +import 'package:flutter/material.dart'; + +typedef Widget MiniplayerBuilder(double height, double percentage); + +class Miniplayer extends StatefulWidget { + final double minHeight; + final double maxHeight; + final MiniplayerBuilder builder; + final Curve curve; + + const Miniplayer( + {Key key, + @required this.minHeight, + @required this.maxHeight, + @required this.builder, + this.curve = Curves.easeInQuart}) + : super(key: key); + + @override + _MiniplayerState createState() => _MiniplayerState(); +} + +class _MiniplayerState extends State with TickerProviderStateMixin { + double _height; + double _prevHeight; + + //Used to set Size after animation is complete + double _endHeight; + bool _up; + + StreamController _heightController = + StreamController.broadcast(); + AnimationController _animationController; + Animation _sizeAnimation; + + @override + void initState() { + _animationController = AnimationController( + vsync: this, + duration: Duration( + milliseconds: 300, + ), + ); + + _animationController.addStatusListener((status) { + if (status == AnimationStatus.completed) { + _animationController.reset(); + _heightController.add(_endHeight); + _height = _endHeight; + } + }); + + _height = widget.minHeight; + super.initState(); + } + + @override + void dispose() { + _heightController.close(); + _animationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return StreamBuilder( + initialData: widget.minHeight, + stream: _heightController.stream, + builder: (context, AsyncSnapshot snapshot) { + if (snapshot.hasData) { + var _percentage = ((snapshot.data - widget.minHeight)) / + (widget.maxHeight - widget.minHeight); + + return Stack( + alignment: Alignment.bottomCenter, + children: [ + if (_percentage > 0) + GestureDetector( + onTap: () => animateToHeight(widget.minHeight), + child: Container( + color: Colors.black.withOpacity(_percentage * 0.5)), + ), + SizedBox( + height: snapshot.data, + child: GestureDetector( + child: widget.builder(snapshot.data, _percentage), + onTap: () { + bool up = _height != widget.maxHeight; + animateToHeight(up ? widget.maxHeight : widget.minHeight); + }, + onPanEnd: (details) async { + if (_up) + animateToHeight(widget.maxHeight); + else + animateToHeight(widget.minHeight); + }, + onPanUpdate: (details) { + _prevHeight = _height; + var h = _height -= + details.delta.dy; //details.delta.dy < 0 -> -- = + + + //Make sure height !> maxHeight && !< minHeight + if (h > widget.maxHeight) + h = widget.maxHeight; + else if (h < widget.minHeight) h = widget.minHeight; + + if (_prevHeight == h && + (h == widget.minHeight || h == widget.maxHeight)) + return; + + //print('h: ' + h.toString()); + + _height = h; + _up = _prevHeight < _height; + + _heightController.add(h); + }, + ), + ), + ], + ); + } else + return Container(); + }, + ); + } + + void animateToHeight(final double h) { + _endHeight = h; + _sizeAnimation = Tween( + begin: _height, + end: h, + ).animate( + CurvedAnimation(parent: _animationController, curve: widget.curve)); + + _sizeAnimation.addListener(() { + _heightController.add(_sizeAnimation.value); + }); + _animationController.forward(); + } } diff --git a/pubspec.yaml b/pubspec.yaml index 965f6ba..59f4ed4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,8 +1,8 @@ name: miniplayer description: Miniplayer for Flutter version: 0.0.1 -author: -homepage: +author: David Peters +homepage: peterscode.dev environment: sdk: ">=2.7.0 <3.0.0" @@ -12,10 +12,6 @@ dependencies: flutter: sdk: flutter -dev_dependencies: - flutter_test: - sdk: flutter - # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/test/miniplayer_test.dart b/test/miniplayer_test.dart deleted file mode 100644 index 7116eaa..0000000 --- a/test/miniplayer_test.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; - -import 'package:miniplayer/miniplayer.dart'; - -void main() { - test('adds one to input values', () { - final calculator = Calculator(); - expect(calculator.addOne(2), 3); - expect(calculator.addOne(-7), -6); - expect(calculator.addOne(0), 1); - expect(() => calculator.addOne(null), throwsNoSuchMethodError); - }); -}