From de7e89f8cf3f6f0142343c85f2b209f078dcfb3a Mon Sep 17 00:00:00 2001 From: David <8vsxdxd@gmail.com> Date: Tue, 6 Oct 2020 20:57:24 +0200 Subject: [PATCH] Add MiniplayerController --- lib/miniplayer.dart | 98 ++++++++++++++++++++++++++++++++++++++------- lib/src/utils.dart | 17 +++++++- pubspec.yaml | 2 +- 3 files changed, 101 insertions(+), 16 deletions(-) diff --git a/lib/miniplayer.dart b/lib/miniplayer.dart index 668a2d5..d02d0f5 100644 --- a/lib/miniplayer.dart +++ b/lib/miniplayer.dart @@ -38,6 +38,8 @@ class Miniplayer extends StatefulWidget { ///If onDismiss is set, the miniplayer can be dismissed final Function onDismiss; + final MiniplayerController controller; + const Miniplayer({ Key key, @required this.minHeight, @@ -49,6 +51,7 @@ class Miniplayer extends StatefulWidget { this.valueNotifier, this.duration = const Duration(milliseconds: 300), this.onDismiss, + this.controller, }) : super(key: key); @override @@ -59,7 +62,7 @@ class _MiniplayerState extends State with TickerProviderStateMixin { ValueNotifier heightNotifier; ValueNotifier dragDownPercentage = ValueNotifier(0); - SnapPosition snap; + PanelState snap; ///Current y position of drag gesture double _dragHeight; @@ -82,11 +85,11 @@ class _MiniplayerState extends State with TickerProviderStateMixin { if (status == AnimationStatus.completed) _resetAnimationController(); } - void _resetAnimationController() { + void _resetAnimationController({Duration duration}) { if (_animationController != null) _animationController.dispose(); _animationController = AnimationController( vsync: this, - duration: widget.duration, + duration: duration == null ? widget.duration : duration, ); _animationController.addStatusListener(_statusListener); animating = false; @@ -103,6 +106,37 @@ class _MiniplayerState extends State with TickerProviderStateMixin { _dragHeight = widget.minHeight; + if (widget.controller != null) { + widget.controller.addListener(() { + switch (widget.controller.value.height) { + case -1: + _animateToHeight( + widget.minHeight, + duration: widget.controller.value.duration, + ); + break; + case -2: + _animateToHeight( + widget.maxHeight, + duration: widget.controller.value.duration, + ); + break; + case -3: + _animateToHeight( + -1, + duration: widget.controller.value.duration, + ); + break; + default: + _animateToHeight( + widget.controller.value.height.toDouble(), + duration: widget.controller.value.duration, + ); + break; + } + }); + } + super.initState(); } @@ -171,8 +205,8 @@ class _MiniplayerState extends State with TickerProviderStateMixin { ), ), onTap: () => _snapToPosition(_dragHeight != widget.maxHeight - ? SnapPosition.MAX - : SnapPosition.MIN), + ? PanelState.MAX + : PanelState.MIN), onPanStart: (details) { _startHeight = _dragHeight; updateCount = 0; @@ -197,7 +231,7 @@ class _MiniplayerState extends State with TickerProviderStateMixin { else if (speed <= 50) snapPercentage = 0.01; ///Determine to which SnapPosition the widget should snap - SnapPosition snap = SnapPosition.MIN; + PanelState snap = PanelState.MIN; final _percentageMax = percentageFromValueInRange( min: widget.minHeight, @@ -207,13 +241,13 @@ class _MiniplayerState extends State with TickerProviderStateMixin { ///Started from expanded state if (_startHeight > widget.minHeight) { if (_percentageMax > 1 - snapPercentage) - snap = SnapPosition.MAX; + snap = PanelState.MAX; } ///Started from minified state else { if (_percentageMax > snapPercentage) - snap = SnapPosition.MAX; + snap = PanelState.MAX; else ///DismissedPercentage > 0.2 -> dismiss @@ -222,7 +256,7 @@ class _MiniplayerState extends State with TickerProviderStateMixin { min: widget.minHeight, max: 0, value: _dragHeight) > - snapPercentage) snap = SnapPosition.DISMISS; + snapPercentage) snap = PanelState.DISMISS; } ///Snap to position @@ -278,24 +312,26 @@ class _MiniplayerState extends State with TickerProviderStateMixin { } ///Animates the panel height according to a SnapPoint - void _snapToPosition(SnapPosition snapPosition) { + void _snapToPosition(PanelState snapPosition) { switch (snapPosition) { - case SnapPosition.MAX: + case PanelState.MAX: _animateToHeight(widget.maxHeight); return; - case SnapPosition.MIN: + case PanelState.MIN: _animateToHeight(widget.minHeight); return; - case SnapPosition.DISMISS: + case PanelState.DISMISS: _animateToHeight(0); return; } } ///Animates the panel height to a specific value - void _animateToHeight(final double h) { + void _animateToHeight(final double h, {Duration duration}) { final startHeight = _dragHeight; + if (duration != null) _resetAnimationController(duration: duration); + Animation _sizeAnimation = Tween( begin: startHeight, end: h, @@ -314,3 +350,37 @@ class _MiniplayerState extends State with TickerProviderStateMixin { _animationController.forward(from: 0); } } + +///-1 Min, -2 Max, -3 Dismiss +enum PanelState { MAX, MIN, DISMISS } + +class ControllerData { + final int height; + final Duration duration; + + const ControllerData(this.height, this.duration); +} + +class MiniplayerController extends ValueNotifier { + MiniplayerController() : super(null); + + void animateToHeight( + {double height, PanelState state, Duration duration}) { + if (height == null && state == null) return; + if (height != null && state != null) return; + + ControllerData valBefore = value; + + if (state != null) + value = ControllerData(state.heightCode, duration); + else { + if (height < 0) return; + + value = ControllerData(height.round(), duration); + } + + if (valBefore == value) notifyListeners(); + } + + void dismiss() {} +} diff --git a/lib/src/utils.dart b/lib/src/utils.dart index 71c4f6c..28134a2 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -1,4 +1,19 @@ -enum SnapPosition { MAX, MIN, DISMISS } +import 'package:miniplayer/miniplayer.dart'; + +extension SelectedColorExtension on PanelState { + int get heightCode { + switch (this) { + case PanelState.MIN: + return -1; + case PanelState.MAX: + return -2; + case PanelState.DISMISS: + return -3; + default: + return -1; + } + } +} ///Calculates the percentage of a value within a given range of values double percentageFromValueInRange({final double min, max, value}) { diff --git a/pubspec.yaml b/pubspec.yaml index 2e12592..e105987 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,7 +5,7 @@ homepage: https://www.peterscode.dev repository: https://github.com/peterscodee/miniplayer environment: - sdk: ">=2.3.0 <3.0.0" + sdk: ">=2.6.0 <3.0.0" flutter: ">=1.0.0 <2.0.0" dependencies: