From 23488a9c05f577397e021e27ac6aab6b9dacc2f0 Mon Sep 17 00:00:00 2001 From: zarzet Date: Mon, 13 Jul 2026 21:00:42 +0700 Subject: [PATCH] feat(player): fade the sheet in place on close, letting only the cover travel Button/back pops no longer slide the sheet down: it dissolves where it stands while the Hero artwork flies back to the mini player. Drag dismissals keep sliding from the finger's position since freezing a half-dragged sheet mid-screen would look broken. --- lib/screens/now_playing_screen.dart | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/lib/screens/now_playing_screen.dart b/lib/screens/now_playing_screen.dart index b5ae9985..5478021c 100644 --- a/lib/screens/now_playing_screen.dart +++ b/lib/screens/now_playing_screen.dart @@ -28,6 +28,7 @@ class NowPlayingRoute extends PageRoute { NowPlayingRoute() : super(fullscreenDialog: true); bool _dragging = false; + bool _popViaDrag = false; @override Color? get barrierColor => null; @@ -60,6 +61,7 @@ class NowPlayingRoute extends PageRoute { final velocity = (details.primaryVelocity ?? 0) / pageHeight; final value = controller?.value ?? 1.0; if (velocity > 1.0 || (velocity >= 0 && value < 0.7)) { + _popViaDrag = true; navigator?.pop(); } else { controller?.fling(); @@ -88,24 +90,30 @@ class NowPlayingRoute extends PageRoute { Animation secondaryAnimation, Widget child, ) { + final reversing = animation.status == AnimationStatus.reverse; + // Button/back pop: the sheet stays put and fades out where it is, so the + // Hero cover is the only thing traveling down to the mini player. A drag + // dismissal instead keeps sliding from the finger's position, dissolving + // on the way down. + final inPlacePop = reversing && !_popViaDrag; // Linear while dragging so the page tracks the finger 1:1. - final position = _dragging + final slide = _dragging ? animation : CurvedAnimation( parent: animation, curve: Easing.emphasizedDecelerate, reverseCurve: Easing.emphasizedAccelerate, ); - // On pop the content has already faded out, so dissolve the sheet on its - // way down instead of sliding an empty dark surface across the screen. - // Forward (open) and drag keep the sheet fully opaque. - final opacity = animation.status == AnimationStatus.reverse + final position = inPlacePop + ? const AlwaysStoppedAnimation(Offset.zero) + : slide.drive(Tween(begin: const Offset(0, 1), end: Offset.zero)); + final opacity = inPlacePop + ? CurvedAnimation(parent: animation, curve: const Interval(0.3, 1.0)) + : reversing ? CurvedAnimation(parent: animation, curve: const Interval(0.0, 0.5)) : const AlwaysStoppedAnimation(1.0); return SlideTransition( - position: position.drive( - Tween(begin: const Offset(0, 1), end: Offset.zero), - ), + position: position, child: FadeTransition(opacity: opacity, child: child), ); }