Makes drag gestures feel more natural.

This commit is contained in:
David 2020-09-21 00:12:58 +02:00
parent 8d60fda628
commit bc6d580abd
1 changed files with 36 additions and 5 deletions

View File

@ -50,6 +50,9 @@ class _MiniplayerState extends State<Miniplayer> with TickerProviderStateMixin {
bool animating = false; bool animating = false;
///Counts how many updates were required for a distance (onPanUpdate) -> necessary to calculate the drag speed
int updateCount = 0;
StreamController<double> _heightController = StreamController<double> _heightController =
StreamController<double>.broadcast(); StreamController<double>.broadcast();
AnimationController _animationController; AnimationController _animationController;
@ -154,8 +157,28 @@ class _MiniplayerState extends State<Miniplayer> with TickerProviderStateMixin {
onTap: () => snapToPosition(_dragHeight != widget.maxHeight onTap: () => snapToPosition(_dragHeight != widget.maxHeight
? SnapPosition.MAX ? SnapPosition.MAX
: SnapPosition.MIN), : SnapPosition.MIN),
onPanStart: (details) => _startHeight = _dragHeight, onPanStart: (details) {
_startHeight = _dragHeight;
updateCount = 0;
},
onPanEnd: (details) async { onPanEnd: (details) async {
///Calculates drag speed
double speed =
(_dragHeight - _startHeight * _dragHeight < _startHeight
? 1
: -1) /
updateCount *
100;
///Define the percentage distance depending on the speed with which the widget should snap
double snapPercentage = 0.005;
if (speed <= 4)
snapPercentage = 0.2;
else if (speed <= 9)
snapPercentage = 0.08;
else if (speed <= 50) snapPercentage = 0.01;
///Determine to which SnapPosition the widget should snap
SnapPosition snap = SnapPosition.MIN; SnapPosition snap = SnapPosition.MIN;
final _percentageMax = _percentageFromValueInRange( final _percentageMax = _percentageFromValueInRange(
@ -165,12 +188,13 @@ class _MiniplayerState extends State<Miniplayer> with TickerProviderStateMixin {
///Started from expanded state ///Started from expanded state
if (_startHeight > widget.minHeight) { if (_startHeight > widget.minHeight) {
if (_percentageMax > 0.8) snap = SnapPosition.MAX; if (_percentageMax > 1 - snapPercentage)
snap = SnapPosition.MAX;
} }
///Started from minified state ///Started from minified state
else { else {
if (_percentageMax > 0.2) if (_percentageMax > snapPercentage)
snap = SnapPosition.MAX; snap = SnapPosition.MAX;
else else
@ -179,9 +203,10 @@ class _MiniplayerState extends State<Miniplayer> with TickerProviderStateMixin {
min: widget.minHeight, min: widget.minHeight,
max: 0, max: 0,
value: _dragHeight) > value: _dragHeight) >
0.2) snap = SnapPosition.DISMISS; snapPercentage) snap = SnapPosition.DISMISS;
} }
///Snap to position
snapToPosition(snap); snapToPosition(snap);
}, },
onPanUpdate: (details) { onPanUpdate: (details) {
@ -189,6 +214,7 @@ class _MiniplayerState extends State<Miniplayer> with TickerProviderStateMixin {
if (dismissed) return; if (dismissed) return;
_dragHeight -= details.delta.dy; _dragHeight -= details.delta.dy;
updateCount++;
handleHeightChange(); handleHeightChange();
}, },
@ -265,11 +291,16 @@ class _MiniplayerState extends State<Miniplayer> with TickerProviderStateMixin {
} }
} }
//Calculates the percentage of a value within a given range of values ///Calculates the percentage of a value within a given range of values
double _percentageFromValueInRange({final double min, max, value}) { double _percentageFromValueInRange({final double min, max, value}) {
return (value - min) / (max - min); return (value - min) / (max - min);
} }
///Calculates n within a range of values
double _valueFromPercentageInRange({final double min, max, percentage}) {
return percentage * (max - min) + min;
}
double _borderDouble({double minRange, double maxRange, double value}) { double _borderDouble({double minRange, double maxRange, double value}) {
if (value > maxRange) return maxRange; if (value > maxRange) return maxRange;
if (value < minRange) return minRange; if (value < minRange) return minRange;