import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:music_player_miao/common_widget/app_data.dart'; import '../api/api_music_rank.dart'; import '../common/download_manager.dart'; import '../models/getRank_bean.dart'; import '../view_model/rank_view_model.dart'; import 'music_view.dart'; import '../common_widget/Song_widegt.dart'; class RankView extends StatefulWidget { const RankView({super.key}); @override State createState() => _RankViewState(); } class _RankViewState extends State with AutomaticKeepAliveClientMixin { final rankVM = Get.put(RankViewModel()); List rankNames = []; List rankSingerName = []; List rankCoverPath = []; List rankMusicPath = []; List rankMid = []; List songs = []; final downloadManager = Get.put(DownloadManager()); @override bool get wantKeepAlive => true; @override void initState() { super.initState(); _fetchTop50Data(); } Future _onRefresh() async { await _fetchTop50Data(); } Future _fetchTop50Data() async { try { RankBean bean2 = await GetRank().getRank(Authorization: AppData().currentToken); if (bean2.code != 200) return; rankNames.clear(); rankSingerName.clear(); rankCoverPath.clear(); rankMusicPath.clear(); rankMid.clear(); songs.clear(); setState(() { List ids = bean2.data!.map((data) => data.id!).toList(); rankNames = bean2.data!.map((data) => data.name!).toList(); rankSingerName = bean2.data!.map((data) => data.singerName!).toList(); rankCoverPath = bean2.data!.map((data) => data.coverPath == '' ? 'https://api.aspark.cc/image/1/6759856d288fd.jpg' : data.coverPath).toList(); rankMusicPath = bean2.data!.map((data) => data.musicPath ?? '').toList(); rankMid = bean2.data!.map((data) => data.mid).toList(); if (rankNames.isNotEmpty && rankNames.length == rankSingerName.length && rankNames.length == rankCoverPath.length && rankNames.length == rankMusicPath.length) { for (int i = 0; i < rankNames.length; i++) { songs.add(Song( artistPic: rankCoverPath[i], title: rankNames[i], artist: rankSingerName[i], musicurl: rankMusicPath[i], pic: rankCoverPath[i], id: ids[i], likes: null, collection: null, mid: rankMid[i], )); } } }); } catch (e) { print('Error fetching data: $e'); } } @override Widget build(BuildContext context) { super.build(context); return Container( decoration: const BoxDecoration( image: DecorationImage( image: AssetImage("assets/img/app_bg.png"), fit: BoxFit.cover, ), ), child: Scaffold( resizeToAvoidBottomInset: false, backgroundColor: Colors.transparent, body: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 40), //头部 const Center( child: Column( children: [ SizedBox( height: 10, ), Text( '喵听排行榜', style: TextStyle(fontSize: 22, fontWeight: FontWeight.w400), ), SizedBox(height: 10), Text( 'Top50', style: TextStyle( color: Color(0xffCE0000), fontSize: 40, fontWeight: FontWeight.w500), ), ], ), ), const SizedBox(height: 10), InkWell( onTap: () { // 播放全部 Navigator.push( context, MaterialPageRoute( builder: (context) => MusicView( songList: songs, initialSongIndex: 0, onSongStatusChanged: (index, isCollected, isLiked) { setState(() { songs[index].collection = isCollected; songs[index].likes = isLiked; downloadManager.updateSongInfo(songs[index].id, isCollected, isLiked); }); }, ), ), ); }, borderRadius: const BorderRadius.only( topLeft: Radius.circular(20), topRight: Radius.circular(20), ), child: Container( decoration: const BoxDecoration( color: Colors.white, borderRadius: BorderRadius.only( topLeft: Radius.circular(20), topRight: Radius.circular(20), ), ), child: Row( children: [ IconButton( onPressed: null, // 移除按钮的点击事件,因为现在整个容器都是可点击的 icon: Image.asset( "assets/img/button_play.png", width: 20, height: 20, ), ), const Text( '播放全部', style: TextStyle(fontSize: 16), ), const SizedBox(width: 5), const Text( '50', style: TextStyle(fontSize: 16), ), ], ), ), ), Expanded( child: RefreshIndicator( onRefresh: _onRefresh, color: const Color(0xff429482), child: SingleChildScrollView( physics: const AlwaysScrollableScrollPhysics(), // 修改为始终可滚动 child: Container( color: Colors.white, child: Column( children: [ ListView.builder( physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, padding: const EdgeInsets.symmetric( vertical: 5, horizontal: 10), itemCount: rankNames.length, itemBuilder: (context, index) { int rankNum = index + 1; return ListTile( onTap: () { Navigator.push( context, MaterialPageRoute( builder: (context) => MusicView( songList: songs, initialSongIndex: index, onSongStatusChanged: (index, isCollected, isLiked) { setState(() { songs[index].collection = isCollected; songs[index].likes = isLiked; downloadManager.updateSongInfo(songs[index].id, isCollected, isLiked); }); }, ), ), ); }, title: Column( children: [ Row( children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox( width: 25, child: RichText( text: TextSpan( text: rankNum.toString(), style: const TextStyle( fontSize: 20, fontWeight: FontWeight.w700, color: Color(0xffCE0000), ), ), ), ), const SizedBox(width: 10), Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(8), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 5, offset: const Offset(0, 2), ), ], ), child: ClipRRect( borderRadius: BorderRadius.circular(8), child: Image.network( rankCoverPath[index], width: 60, height: 60, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) => Container( width: 60, height: 60, color: Colors.grey[100], child: const Icon(Icons.music_note, size: 30), ), ), ), ), const SizedBox(width: 20), SizedBox( width: 170, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( rankNames[index], maxLines: 1, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w500 ), overflow: TextOverflow.ellipsis, ), Text( rankSingerName[index], maxLines: 1, style: TextStyle( color: Colors.grey[600], fontSize: 14 ), overflow: TextOverflow.ellipsis, ) ], ), ), const SizedBox(width: 18), ], ), ], ), const SizedBox(height: 10) ], ), ); }, ), ], ), ), ), ), ), const SizedBox( height: 130, ), ], ), ), ); } }