Add MiniplayerController

This commit is contained in:
David 2020-10-06 20:57:24 +02:00
parent e1bef9b40f
commit de7e89f8cf
3 changed files with 101 additions and 16 deletions

View File

@ -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<Miniplayer> with TickerProviderStateMixin {
ValueNotifier<double> heightNotifier;
ValueNotifier<double> dragDownPercentage = ValueNotifier(0);
SnapPosition snap;
PanelState snap;
///Current y position of drag gesture
double _dragHeight;
@ -82,11 +85,11 @@ class _MiniplayerState extends State<Miniplayer> 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<Miniplayer> 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<Miniplayer> 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<Miniplayer> 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<Miniplayer> 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<Miniplayer> 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<Miniplayer> 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<double> _sizeAnimation = Tween(
begin: startHeight,
end: h,
@ -314,3 +350,37 @@ class _MiniplayerState extends State<Miniplayer> 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<ControllerData> {
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() {}
}

View File

@ -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}) {

View File

@ -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: