正在播放的自滑动刹车动画动作优化完成,同时调整播放页进入动作

This commit is contained in:
2026-08-28 22:45:14 +08:00
parent 2e55f94df2
commit 86b1d0df42
2 changed files with 116 additions and 63 deletions
+33 -23
View File
@@ -19,17 +19,11 @@ import 'widgets/global_mini_player.dart';
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
final stopwatch = Stopwatch();
// ⭐ 防止 Hot Restart / 热重载时重复初始化
bool _appInitialized = false;
// ⭐ 全局缓存 Handler
AudioPlayerHandler? _audioHandler;
// ⭐ 全局缓存 LifecycleManager
final AppLifecycleManager lifecycleManager = AppLifecycleManager();
void main() async {
// ⭐ P0:防止重复初始化
if (_appInitialized) {
debugPrint('⏱️ main 已初始化,跳过重复执行');
return;
@@ -42,7 +36,6 @@ void main() async {
WidgetsFlutterBinding.ensureInitialized();
debugPrint('⏱️ T0.5 ensureInitialized: ${stopwatch.elapsedMilliseconds}ms');
// ⭐ MediaKit 在 runApp 前初始化(官方要求)
try {
MediaKit.ensureInitialized();
debugPrint('⏱️ T0.6 MediaKit 初始化完成');
@@ -50,10 +43,8 @@ void main() async {
debugPrint('❌ MediaKit 初始化失败: $e');
}
// ⭐ 创建 Handler
_audioHandler = AudioPlayerHandler();
// ⭐ 注册切歌回调
AudioService().setOnSongChanged((song) {
debugPrint(
'📢 [main] song.artwork is ${song.artwork != null ? 'not null' : 'null'}');
@@ -81,6 +72,7 @@ void main() async {
debugPrint('⏱️ T0.8 runApp 完成: ${stopwatch.elapsedMilliseconds}ms');
// ⭐ 首帧后恢复播放状态
WidgetsBinding.instance.addPostFrameCallback((_) {
AudioService().restorePlaybackState();
});
@@ -112,13 +104,10 @@ class RouteManager extends ChangeNotifier {
// ════════════════════════════════════════════════════════════
// 导航观察者(监听路由变化)
// ════════════════════════════════════════════════════════════
// lib/main.dart
class MiniPlayerNavigatorObserver extends NavigatorObserver {
void _updateRoute(Route? route) {
if (route == null) return;
// ⭐ 忽略 PopupRoute(菜单、对话框等)
if (route is PopupRoute) {
return;
}
@@ -134,7 +123,6 @@ class MiniPlayerNavigatorObserver extends NavigatorObserver {
@override
void didPop(Route route, Route? previousRoute) {
// ⭐ 返回时,使用上一个路由(previousRoute
if (previousRoute != null && previousRoute is! PopupRoute) {
final name = previousRoute.settings.name ?? '/';
RouteManager().updateRoute(name);
@@ -275,9 +263,11 @@ class _QTPlayerAppState extends State<QTPlayerApp> {
return '${DateTime.now().difference(start).inMilliseconds}';
}
// ⭐ 路由生成(播放页滑入动画,速度 200ms)
// lib/main.dart - _onGenerateRoute 方法
// ════════════════════════════════════════════════════════════
// ⭐ 路由生成(播放页 & 播放列表页底部滑入)
// ════════════════════════════════════════════════════════════
Route<dynamic> _onGenerateRoute(RouteSettings settings) {
// ⭐ 播放页:底部滑入
if (settings.name == '/player') {
return PageRouteBuilder(
settings: settings,
@@ -285,12 +275,9 @@ class _QTPlayerAppState extends State<QTPlayerApp> {
return const PlayerPage();
},
transitionsBuilder: (context, animation, secondaryAnimation, child) {
// ⭐ 应用贝塞尔曲线
final curvedAnimation = CurvedAnimation(
parent: animation,
curve: Curves.easeOutCubic, // 平滑减速
// curve: Curves.easeOutBack, // 轻微回弹,更灵动
// curve: Curves.fastOutSlowIn, // Material 风格
curve: Curves.easeOutCubic,
);
const begin = Offset(0.0, 1.0);
const end = Offset.zero;
@@ -301,18 +288,42 @@ class _QTPlayerAppState extends State<QTPlayerApp> {
child: child,
);
},
transitionDuration: const Duration(milliseconds: 300),
transitionDuration: const Duration(milliseconds: 250),
);
}
// ⭐ 播放列表页:底部滑入(与播放页一致)
if (settings.name == '/playlist') {
return PageRouteBuilder(
settings: settings,
pageBuilder: (context, animation, secondaryAnimation) {
return const PlaylistPage();
},
transitionsBuilder: (context, animation, secondaryAnimation, child) {
final curvedAnimation = CurvedAnimation(
parent: animation,
curve: Curves.easeOutCubic,
);
const begin = Offset(0.0, 1.0);
const end = Offset.zero;
final tween = Tween(begin: begin, end: end);
final offsetAnimation = tween.animate(curvedAnimation);
return SlideTransition(
position: offsetAnimation,
child: child,
);
},
transitionDuration: const Duration(milliseconds: 250),
);
}
// 其他页面使用默认
return MaterialPageRoute(
settings: settings,
builder: (context) {
switch (settings.name) {
case '/':
return const HomePage();
case '/playlist':
return const PlaylistPage();
default:
return const HomePage();
}
@@ -359,7 +370,6 @@ class _QTPlayerAppState extends State<QTPlayerApp> {
switchInCurve: Curves.easeOut,
switchOutCurve: Curves.easeIn,
transitionBuilder: (child, animation) {
// ⭐ 淡入淡出 + 轻微上滑
return FadeTransition(
opacity: animation,
child: SlideTransition(