播放页部分调整,完整播放链路层级已打通
This commit is contained in:
+152
-57
@@ -6,22 +6,119 @@ import 'services/audio_service.dart';
|
||||
import 'services/playback_service.dart';
|
||||
import 'pages/home_page.dart';
|
||||
import 'pages/player_page.dart';
|
||||
import 'pages/playlist_page.dart'; // ✅ 导入 PlaylistPage
|
||||
import 'widgets/global_mini_player.dart';
|
||||
|
||||
// ✅ 全局导航键
|
||||
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||||
|
||||
void main() {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
bool initSuccess = false;
|
||||
String? initError;
|
||||
|
||||
try {
|
||||
MediaKit.ensureInitialized();
|
||||
PlaybackService().init();
|
||||
initSuccess = true;
|
||||
} catch (e, stack) {
|
||||
print('❌ 初始化失败: $e');
|
||||
initError = '初始化失败: $e';
|
||||
print('❌ $initError');
|
||||
print(stack);
|
||||
runApp(
|
||||
MaterialApp(
|
||||
}
|
||||
|
||||
runApp(
|
||||
ChangeNotifierProvider(
|
||||
create: (_) => AudioService(),
|
||||
child: QTPlayerApp(
|
||||
initSuccess: initSuccess,
|
||||
initError: initError,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class QTPlayerApp extends StatefulWidget {
|
||||
final bool initSuccess;
|
||||
final String? initError;
|
||||
|
||||
const QTPlayerApp({
|
||||
super.key,
|
||||
required this.initSuccess,
|
||||
required this.initError,
|
||||
});
|
||||
|
||||
@override
|
||||
State<QTPlayerApp> createState() => _QTPlayerAppState();
|
||||
}
|
||||
|
||||
class _QTPlayerAppState extends State<QTPlayerApp>
|
||||
with SingleTickerProviderStateMixin {
|
||||
bool _showPlayerPage = false;
|
||||
bool _showPlaylist = false; // ✅ 新增:播放列表显示状态
|
||||
|
||||
late final AnimationController _animationController;
|
||||
late final Animation<double> _slideAnimation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
GlobalMiniPlayer.onOpenPlayerPage = _openPlayerPage;
|
||||
GlobalMiniPlayer.onOpenPlaylistPage = _openPlaylist;
|
||||
|
||||
_animationController = AnimationController(
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
);
|
||||
|
||||
_slideAnimation = Tween<double>(begin: 1.0, end: 0.0).animate(
|
||||
CurvedAnimation(
|
||||
parent: _animationController,
|
||||
curve: Curves.easeOutCubic,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_animationController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _openPlayerPage() {
|
||||
setState(() {
|
||||
_showPlayerPage = true;
|
||||
_showPlaylist = false; // 打开播放页时关闭播放列表
|
||||
});
|
||||
_animationController.forward(from: 0.0);
|
||||
}
|
||||
|
||||
void _closePlayerPage() {
|
||||
_animationController.reverse().then((_) {
|
||||
setState(() {
|
||||
_showPlayerPage = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ✅ 打开播放列表
|
||||
void _openPlaylist() {
|
||||
setState(() {
|
||||
_showPlaylist = true;
|
||||
});
|
||||
}
|
||||
|
||||
// ✅ 关闭播放列表
|
||||
void _closePlaylist() {
|
||||
setState(() {
|
||||
_showPlaylist = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (!widget.initSuccess) {
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
backgroundColor: const Color(0xFF0E1211),
|
||||
body: Center(
|
||||
@@ -30,70 +127,42 @@ void main() {
|
||||
children: [
|
||||
Icon(Icons.error_outline, size: 64, color: Colors.red[300]),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
const Text(
|
||||
'应用初始化失败',
|
||||
style: TextStyle(color: Colors.white, fontSize: 20),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'$e',
|
||||
widget.initError ?? '未知错误',
|
||||
style: TextStyle(color: Colors.grey[400], fontSize: 14),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
runApp(
|
||||
ChangeNotifierProvider(
|
||||
create: (_) => AudioService(),
|
||||
child: QTPlayerApp(
|
||||
initSuccess: true,
|
||||
initError: null,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFFB8D4D0),
|
||||
foregroundColor: Colors.black87,
|
||||
),
|
||||
child: const Text('重试'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
FlutterError.onError = (details) {
|
||||
print('❌ Flutter Error: ${details.exception}');
|
||||
print('Stack: ${details.stack}');
|
||||
};
|
||||
|
||||
runApp(
|
||||
ChangeNotifierProvider(
|
||||
create: (_) => AudioService(),
|
||||
child: const QTPlayerApp(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class QTPlayerApp extends StatefulWidget {
|
||||
const QTPlayerApp({super.key});
|
||||
|
||||
@override
|
||||
State<QTPlayerApp> createState() => _QTPlayerAppState();
|
||||
}
|
||||
|
||||
class _QTPlayerAppState extends State<QTPlayerApp> {
|
||||
bool _showPlayerPage = false;
|
||||
|
||||
// ✅ 播放页回调,暴露给 GlobalMiniPlayer
|
||||
void _openPlayerPage() {
|
||||
setState(() {
|
||||
_showPlayerPage = true;
|
||||
});
|
||||
}
|
||||
|
||||
void _closePlayerPage() {
|
||||
setState(() {
|
||||
_showPlayerPage = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// ✅ 注入回调(GlobalMiniPlayer 是 static 成员)
|
||||
GlobalMiniPlayer.onOpenPlayerPage = _openPlayerPage;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: '清听',
|
||||
navigatorKey: navigatorKey,
|
||||
@@ -117,6 +186,7 @@ class _QTPlayerAppState extends State<QTPlayerApp> {
|
||||
children: [
|
||||
// ① 主页面
|
||||
Positioned.fill(child: child!),
|
||||
|
||||
// ② MiniPlayer
|
||||
const Positioned(
|
||||
left: 0,
|
||||
@@ -124,11 +194,36 @@ class _QTPlayerAppState extends State<QTPlayerApp> {
|
||||
bottom: 0,
|
||||
child: GlobalMiniPlayer(),
|
||||
),
|
||||
|
||||
// ③ 播放页(全屏覆盖)
|
||||
if (_showPlayerPage)
|
||||
Positioned.fill(
|
||||
child: PlayerPage(
|
||||
onClose: _closePlayerPage,
|
||||
child: AnimatedBuilder(
|
||||
animation: _animationController,
|
||||
builder: (context, child) {
|
||||
final progress = _slideAnimation.value;
|
||||
final offsetY =
|
||||
MediaQuery.of(context).size.height * progress;
|
||||
return Transform.translate(
|
||||
offset: Offset(0, offsetY),
|
||||
child: Opacity(
|
||||
opacity: 1.0 - progress * 0.3,
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: PlayerPage(
|
||||
onClose: _closePlayerPage,
|
||||
onOpenPlaylist: _openPlaylist, // ✅ 传入回调
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// ④ ✅ 播放列表(最高层级,在播放页之上)
|
||||
if (_showPlaylist)
|
||||
Positioned.fill(
|
||||
child: PlaylistPage(
|
||||
onClose: _closePlaylist,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user