// lib/pages/player_page.dart import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../services/audio_service.dart'; class PlayerPage extends StatefulWidget { const PlayerPage({super.key}); @override State createState() => _PlayerPageState(); } class _PlayerPageState extends State { // ✅ 使用 late,但不赋值,在 didChangeDependencies 中初始化 late AudioService _audioService; @override void didChangeDependencies() { super.didChangeDependencies(); // ✅ 只在第一次或 service 变化时赋值 _audioService = context.watch(); } String _formatDuration(Duration d) { final minutes = d.inMinutes; final seconds = d.inSeconds % 60; return '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}'; } @override Widget build(BuildContext context) { // ✅ 使用 watch 实时获取状态 final service = context.watch(); final song = service.currentSong; if (song == null) { return Scaffold( backgroundColor: const Color(0xFF0E1211), body: const Center( child: Text( '没有正在播放的歌曲', style: TextStyle(color: Colors.grey), ), ), ); } final position = service.position; final duration = service.duration; final isPlaying = service.isPlaying; final progress = duration.inMilliseconds > 0 ? position.inMilliseconds / duration.inMilliseconds : 0.0; return Scaffold( backgroundColor: const Color(0xFF0E1211), appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0, leading: IconButton( icon: const Icon(Icons.arrow_back_ios_new, color: Colors.white), onPressed: () => Navigator.pop(context), ), actions: [ IconButton( icon: const Icon(Icons.more_vert, color: Colors.white54), onPressed: () {}, ), ], ), body: Padding( padding: const EdgeInsets.symmetric(horizontal: 24), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( width: 280, height: 280, decoration: BoxDecoration( shape: BoxShape.circle, color: const Color(0xFF2A3332), boxShadow: [ BoxShadow( color: const Color(0xFF7C9A9E).withOpacity(0.15), blurRadius: 60, spreadRadius: 10, ), ], ), child: const Icon( Icons.music_note, size: 80, color: Colors.white24, ), ), const SizedBox(height: 48), Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( song.title, style: const TextStyle( fontSize: 22, fontWeight: FontWeight.w600, color: Colors.white, ), textAlign: TextAlign.center, ), const SizedBox(height: 8), Text( song.artist, style: TextStyle( fontSize: 16, color: Colors.grey[400], ), textAlign: TextAlign.center, ), ], ), const SizedBox(height: 40), Column( children: [ Slider( value: progress.clamp(0.0, 1.0), onChanged: (value) { final newPosition = Duration( milliseconds: (value * duration.inMilliseconds).round(), ); service.seekTo(newPosition); }, activeColor: const Color(0xFFB8D4D0), inactiveColor: Colors.grey[800], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( _formatDuration(position), style: TextStyle( fontSize: 12, color: Colors.grey[500], ), ), Text( _formatDuration(duration), style: TextStyle( fontSize: 12, color: Colors.grey[500], ), ), ], ), ], ), const SizedBox(height: 32), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ IconButton( onPressed: () {}, icon: const Icon(Icons.skip_previous, size: 32), color: Colors.white60, padding: const EdgeInsets.all(16), ), const SizedBox(width: 24), Container( width: 64, height: 64, decoration: BoxDecoration( color: const Color(0xFFB8D4D0), shape: BoxShape.circle, ), child: IconButton( icon: Icon( isPlaying ? Icons.pause : Icons.play_arrow, color: Colors.black87, size: 32, ), padding: EdgeInsets.zero, onPressed: () { service.togglePlay(); }, ), ), const SizedBox(width: 24), IconButton( onPressed: () {}, icon: const Icon(Icons.skip_next, size: 32), color: Colors.white60, padding: const EdgeInsets.all(16), ), ], ), const SizedBox(height: 32), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ IconButton( onPressed: () {}, icon: const Icon(Icons.volume_up_outlined), color: Colors.white38, ), ], ), ], ), ), ); } }