diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts index 950c9a5..c21f0c5 100644 --- a/android/settings.gradle.kts +++ b/android/settings.gradle.kts @@ -20,7 +20,7 @@ pluginManagement { plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" id("com.android.application") version "9.0.1" apply false - id("org.jetbrains.kotlin.android") version "2.2.20" apply false + id("org.jetbrains.kotlin.android") version "2.3.20" apply false } include(":app") diff --git a/lib/main.dart b/lib/main.dart index 93683ed..bfed8d8 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,6 +5,7 @@ import 'package:media_kit/media_kit.dart'; import 'package:audio_service/audio_service.dart' as audio_service; import 'package:permission_handler/permission_handler.dart'; +import 'package:flutter/services.dart'; import 'services/audio_service.dart'; import 'services/playback_service.dart'; import 'services/app_lifecycle_service.dart'; @@ -15,8 +16,8 @@ import 'pages/home_page.dart'; import 'pages/player_page.dart'; import 'pages/playlist_page.dart'; import 'widgets/global_mini_player.dart'; +import 'utils/navigation.dart'; -final GlobalKey navigatorKey = GlobalKey(); final stopwatch = Stopwatch(); bool _appInitialized = false; @@ -363,65 +364,74 @@ class _QTPlayerAppState extends State { debugPrint( '🎨 [QTPlayerApp] build #$_buildCount ${stopwatch.elapsedMilliseconds}ms'); - return MaterialApp( - title: '清听', - theme: ThemeData( - brightness: Brightness.dark, - primaryColor: const Color(0xFF7C9A9E), - colorScheme: const ColorScheme.dark( - primary: Color(0xFF7C9A9E), - secondary: Color(0xFFB8D4D0), - surface: Color(0xFF1A1F1E), - onSurface: Colors.white, - ), - useMaterial3: true, + // ⭐ 使用 AnnotatedRegion 包裹 MaterialApp,统一控制系统栏样式 + return AnnotatedRegion( + value: SystemUiOverlayStyle( + statusBarColor: Colors.transparent, + statusBarIconBrightness: Brightness.light, + systemNavigationBarColor: const Color(0xFF1A1F1E), + systemNavigationBarIconBrightness: Brightness.light, ), - navigatorKey: navigatorKey, - navigatorObservers: [MiniPlayerNavigatorObserver()], - onGenerateRoute: _onGenerateRoute, - builder: (context, child) { - return Stack( - fit: StackFit.expand, - children: [ - if (child != null) child, - AnimatedBuilder( - animation: RouteManager(), - builder: (context, _) { - final routeManager = RouteManager(); - final shouldShow = routeManager.currentRoute != '/player' && - routeManager.currentRoute != '/playlist'; + child: MaterialApp( + title: '清听', + theme: ThemeData( + brightness: Brightness.dark, + primaryColor: const Color(0xFF7C9A9E), + colorScheme: const ColorScheme.dark( + primary: Color(0xFF7C9A9E), + secondary: Color(0xFFB8D4D0), + surface: Color(0xFF1A1F1E), + onSurface: Colors.white, + ), + useMaterial3: true, + ), + navigatorKey: navigatorKey, + navigatorObservers: [MiniPlayerNavigatorObserver()], + onGenerateRoute: _onGenerateRoute, + builder: (context, child) { + return Stack( + fit: StackFit.expand, + children: [ + if (child != null) child, + AnimatedBuilder( + animation: RouteManager(), + builder: (context, _) { + final routeManager = RouteManager(); + final shouldShow = routeManager.currentRoute != '/player' && + routeManager.currentRoute != '/playlist'; - return AnimatedSwitcher( - duration: const Duration(milliseconds: 300), - switchInCurve: Curves.easeOut, - switchOutCurve: Curves.easeIn, - transitionBuilder: (child, animation) { - return FadeTransition( - opacity: animation, - child: SlideTransition( - position: Tween( - begin: const Offset(0, 0.1), - end: Offset.zero, - ).animate(animation), - child: child, - ), - ); - }, - child: shouldShow - ? const Align( - key: ValueKey('mini_player_visible'), - alignment: Alignment.bottomCenter, - child: GlobalMiniPlayer(), - ) - : const SizedBox.shrink( - key: ValueKey('mini_player_hidden'), + return AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + switchInCurve: Curves.easeOut, + switchOutCurve: Curves.easeIn, + transitionBuilder: (child, animation) { + return FadeTransition( + opacity: animation, + child: SlideTransition( + position: Tween( + begin: const Offset(0, 0.1), + end: Offset.zero, + ).animate(animation), + child: child, ), - ); - }, - ), - ], - ); - }, + ); + }, + child: shouldShow + ? const Align( + key: ValueKey('mini_player_visible'), + alignment: Alignment.bottomCenter, + child: GlobalMiniPlayer(), + ) + : const SizedBox.shrink( + key: ValueKey('mini_player_hidden'), + ), + ); + }, + ), + ], + ); + }, + ), ); } } diff --git a/lib/utils/navigation.dart b/lib/utils/navigation.dart new file mode 100644 index 0000000..5691d87 --- /dev/null +++ b/lib/utils/navigation.dart @@ -0,0 +1,3 @@ +import 'package:flutter/material.dart'; + +final GlobalKey navigatorKey = GlobalKey(); diff --git a/lib/widgets/global_mini_player.dart b/lib/widgets/global_mini_player.dart index 14a1383..df7c722 100644 --- a/lib/widgets/global_mini_player.dart +++ b/lib/widgets/global_mini_player.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../services/audio_service.dart'; +import '../utils/navigation.dart'; // ⭐ 导入 navigatorKey class GlobalMiniPlayer extends StatelessWidget { const GlobalMiniPlayer({super.key}); @@ -45,11 +46,9 @@ class GlobalMiniPlayer extends StatelessWidget { color: Colors.transparent, child: InkWell( onTap: () { - // ⭐ 使用 Navigator.of(context) 替代 navigatorKey - Navigator.of(context, rootNavigator: true) - .pushNamed('/player'); + // ⭐ 使用 navigatorKey 直接跳转 + navigatorKey.currentState?.pushNamed('/player'); }, - // ⭐ 替换弃用的 withOpacity 为 withValues highlightColor: Colors.white.withValues(alpha: 0.05), splashColor: Colors.white.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(12), @@ -124,8 +123,8 @@ class GlobalMiniPlayer extends StatelessWidget { size: 24, ), onPressed: () { - // ⭐ 使用 Navigator.of(context) - Navigator.of(context).pushNamed('/playlist'); + // ⭐ 使用 navigatorKey 直接跳转 + navigatorKey.currentState?.pushNamed('/playlist'); }, ), const SizedBox(width: 4),