feat: 调整播放器样式, 启用页面保持, 添加下拉刷新

chen
Spark 3 months ago
parent fc613ee961
commit 38921f848f

@ -20,67 +20,77 @@ class HomeView extends StatefulWidget {
State<HomeView> createState() => _HomeViewState(); State<HomeView> createState() => _HomeViewState();
} }
class _HomeViewState extends State<HomeView> { class _HomeViewState extends State<HomeView>
// 使 GetX HomeViewModel homeVM with AutomaticKeepAliveClientMixin {
// Get.put() HomeViewModel GetX 便使
final homeVM = Get.put(HomeViewModel()); final homeVM = Get.put(HomeViewModel());
// TextEditingController
//
final TextEditingController _controller = TextEditingController(); final TextEditingController _controller = TextEditingController();
// _isSearching
// _isSearching true_isSearching false
bool _isSearching = false; bool _isSearching = false;
final downloadManager = Get.put(DownloadManager()); final downloadManager = Get.put(DownloadManager());
List<Song> selectedSongs = [];
@override
bool get wantKeepAlive => true;
@override
void initState() { void initState() {
super.initState(); super.initState();
_fetchSonglistData(); _fetchSonglistData();
} }
List<Song> selectedSongs = [];
Future<void> _fetchSonglistData() async {
MusicListBean bean1 =
await GetMusic().getMusic1(Authorization: AppData().currentToken);
MusicListBean bean2 =
await GetMusic().getMusic2(Authorization: AppData().currentToken);
MusicListBean bean3 =
await GetMusic().getMusic3(Authorization: AppData().currentToken);
setState(() { Future<void> _onRefresh() async {
selectedSongs = [ try {
Song( //
artistPic: bean1.coverPath!, await _fetchSonglistData();
title: bean1.name!, } catch (e) {
artist: bean1.singerName!, print('Refresh error: $e');
musicurl: bean1.musicPath!, //
pic: bean1.coverPath!, }
id: bean1.id!,
likes: bean1.likeOrNot!,
collection: bean1.collectOrNot!),
Song(
artistPic: bean2.coverPath!,
title: bean2.name!,
artist: bean2.singerName!,
musicurl: bean2.musicPath!,
pic: bean2.coverPath!,
id: bean2.id!,
likes: bean2.likeOrNot!,
collection: bean2.collectOrNot!),
Song(
artistPic: bean3.coverPath!,
title: bean3.name!,
artist: bean3.singerName!,
musicurl: bean3.musicPath!,
pic: bean3.coverPath!,
id: bean3.id!,
likes: bean3.likeOrNot!,
collection: bean3.collectOrNot!),
];
});
} }
Future<void> _fetchSonglistData() async {
try {
MusicListBean bean1 =
await GetMusic().getMusic1(Authorization: AppData().currentToken);
MusicListBean bean2 =
await GetMusic().getMusic2(Authorization: AppData().currentToken);
MusicListBean bean3 =
await GetMusic().getMusic3(Authorization: AppData().currentToken);
setState(() {
selectedSongs = [
Song(
artistPic: bean1.coverPath!,
title: bean1.name!,
artist: bean1.singerName!,
musicurl: bean1.musicPath!,
pic: bean1.coverPath!,
id: bean1.id!,
likes: bean1.likeOrNot!,
collection: bean1.collectOrNot!),
Song(
artistPic: bean2.coverPath!,
title: bean2.name!,
artist: bean2.singerName!,
musicurl: bean2.musicPath!,
pic: bean2.coverPath!,
id: bean2.id!,
likes: bean2.likeOrNot!,
collection: bean2.collectOrNot!),
Song(
artistPic: bean3.coverPath!,
title: bean3.name!,
artist: bean3.singerName!,
musicurl: bean3.musicPath!,
pic: bean3.coverPath!,
id: bean3.id!,
likes: bean3.likeOrNot!,
collection: bean3.collectOrNot!),
];
});
} catch (e) {
print('Error occurred while fetching song list: $e');
}
}
/// ///
List<Map> imgList = [ List<Map> imgList = [
@ -107,32 +117,40 @@ class _HomeViewState extends State<HomeView> {
// id // id
for (var data in bean.data!) { for (var data in bean.data!) {
if (data.id != null) { // id null if (data.id != null) {
// id null
// 使 id Future // 使 id Future
songDetailsFutures.add( songDetailsFutures.add(GetMusicDetail()
GetMusicDetail().getMusicDetail( .getMusicDetail(
songId: data.id!, songId: data.id!,
Authorization: AppData().currentToken, Authorization: AppData().currentToken,
).then((details) { )
if (details != null) { .then((details) {
// Song if (details != null) {
return Song( // Song
artistPic: details.artistPic ?? '', // return Song(
title: data.name ?? '', // artistPic: details.artistPic ?? '',
artist: details.artist ?? '', // //
musicurl: details.musicurl ?? '', // title: data.name ?? '',
pic: details.pic ?? '', // //
id: details.id, // ID artist: details.artist ?? '',
likes: details.likes, // //
collection: details.collection, // musicurl: details.musicurl ?? '',
); //
} pic: details.pic ?? '',
return null; // null //
}).catchError((error) { id: details.id,
print("Error occurred while fetching song details: $error"); // ID
return null; // null likes: details.likes,
}) //
); collection: details.collection, //
);
}
return null; // null
}).catchError((error) {
print("Error occurred while fetching song details: $error");
return null; // null
}));
} else { } else {
print("Song ID is null for song: ${data.name}"); print("Song ID is null for song: ${data.name}");
} }
@ -142,12 +160,15 @@ class _HomeViewState extends State<HomeView> {
List<Song?> songDetailsList = await Future.wait(songDetailsFutures); List<Song?> songDetailsList = await Future.wait(songDetailsFutures);
// null // null
List<Song> validSongDetails = songDetailsList.where((song) => song != null).cast<Song>().toList(); List<Song> validSongDetails = songDetailsList
.where((song) => song != null)
.cast<Song>()
.toList();
// UI _filteredData // UI _filteredData
setState(() { setState(() {
_filteredData = validSongDetails; // _filteredData = validSongDetails; //
_isSearching = true; // _isSearching = true; //
}); });
// //
@ -175,6 +196,8 @@ class _HomeViewState extends State<HomeView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context);
/// ///
var MySwiperWidget = Swiper( var MySwiperWidget = Swiper(
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
@ -205,222 +228,258 @@ class _HomeViewState extends State<HomeView> {
child: Scaffold( child: Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
body: SingleChildScrollView( body: Column(
child: Column( children: [
crossAxisAlignment: CrossAxisAlignment.start, ///
children: [ Container(
/// padding: const EdgeInsets.only(left: 20, top: 50),
Container( child: const Row(
padding: const EdgeInsets.only(left: 20, top: 50), crossAxisAlignment: CrossAxisAlignment.end,
child: const Row( children: [
crossAxisAlignment: CrossAxisAlignment.end, Text(
children: [ '喵听',
Text( style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold),
'喵听', ),
style: SizedBox(width: 10),
TextStyle(fontSize: 35, fontWeight: FontWeight.bold), Text(
), '你的云端音乐库',
SizedBox( style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
width: 10, ),
],
),
),
const SizedBox(height: 10),
///
Container(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Column(
children: [
Container(
height: 38,
decoration: BoxDecoration(
color: const Color(0xffF9F2AF),
borderRadius: BorderRadius.circular(19),
boxShadow: const [
BoxShadow(
color: Colors.black26,
offset: Offset(0, 1),
blurRadius: 0.1,
)
],
), ),
Text( child: TextField(
'你的云端音乐库', controller: _controller,
style: onChanged: (query) {
TextStyle(fontSize: 20, fontWeight: FontWeight.w500), setState(() async {
_filterData(query);
});
},
decoration: InputDecoration(
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
contentPadding: const EdgeInsets.symmetric(
vertical: 4,
horizontal: 20,
),
prefixIcon: Container(
margin: const EdgeInsets.only(left: 20),
alignment: Alignment.centerLeft,
width: 30,
child: Image.asset(
"assets/img/home_search.png",
width: 20,
height: 20,
fit: BoxFit.contain,
),
),
hintText: "大家都在搜《背对背拥抱》",
hintStyle: const TextStyle(
color: Color(0xffA5A5A5),
fontSize: 13,
),
),
), ),
], ),
), if (_isSearching)
),
const SizedBox(height: 10,),
///
Container(
padding: const EdgeInsets.only(left: 20, right: 20, top: 10),
child: Column(
children: [
Container( Container(
height: 38, height: 150,
width: 345,
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xffF9F2AF), color: const Color(0xffF9F2AF).withOpacity(0.7),
borderRadius: BorderRadius.circular(19),
boxShadow: const [
BoxShadow(
color: Colors.black26,
offset: Offset(0, 1),
blurRadius: 0.1,
)
],
), ),
child: TextField( child: ListView.builder(
controller: _controller, padding: EdgeInsets.zero,
onChanged: (query) { itemCount: _filteredData.length,
setState(() async { itemBuilder: (context, index) {
_filterData(query); return ListTile(
}); title: Text(_filteredData[index].title),
onTap: () {
//
Navigator.push(
// 使 Navigator
context,
MaterialPageRoute(
// MusicView
builder: (context) => MusicView(
songList: _filteredData,
//
initialSongIndex:
index, //
),
),
);
},
);
}, },
decoration: InputDecoration(
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
errorBorder: InputBorder.none,
contentPadding: const EdgeInsets.symmetric(
vertical: 4,
horizontal: 20,
),
prefixIcon: Container(
margin: const EdgeInsets.only(left: 20),
alignment: Alignment.centerLeft,
width: 30,
child: Image.asset(
"assets/img/home_search.png",
width: 20,
height: 20,
fit: BoxFit.contain,
),
),
hintText: "大家都在搜《背对背拥抱》",
hintStyle: const TextStyle(
color: Color(0xffA5A5A5),
fontSize: 13,
),
),
), ),
), ),
if (_isSearching) ],
),
),
const SizedBox(
height: 10,
),
///+
Expanded(
child: RefreshIndicator(
onRefresh: _onRefresh,
color: const Color(0xff429482),
backgroundColor: Colors.white,
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
///+
Container( Container(
height: 150, padding:
width: 345, const EdgeInsets.only(left: 20, right: 20, top: 10),
decoration: BoxDecoration( child: const Text(
color: const Color(0xffF9F2AF).withOpacity(0.7), '每日推荐',
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.w500),
), ),
child: ListView.builder( ),
padding: EdgeInsets.zero, const SizedBox(height: 5),
itemCount: _filteredData.length, Container(
itemBuilder: (context, index) { padding: const EdgeInsets.symmetric(
return ListTile( horizontal: 20, vertical: 5),
title: Text(_filteredData[index].title), height: 186,
width: double.infinity,
child: MySwiperWidget,
),
const SizedBox(height: 10),
///
Container(
alignment: Alignment.topLeft,
padding:
const EdgeInsets.only(left: 20, right: 20, top: 5),
child: const Text(
'精选歌曲',
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.w500),
),
),
const SizedBox(
height: 5,
),
ListView.builder(
padding: EdgeInsets.zero,
itemCount: selectedSongs.length,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (context, index) {
return ListTile(
leading: Image.network(selectedSongs[index].pic),
title: Text(
selectedSongs[index].title,
style: const TextStyle(
fontSize: 18, color: Colors.black),
),
subtitle: Text(
selectedSongs[index].artist,
style: const TextStyle(
fontSize: 16, color: Colors.black),
),
trailing: InkWell(
onTap: () { onTap: () {
// _bottomSheet(context, index);
Navigator.push(
// 使 Navigator
context,
MaterialPageRoute(
// MusicView
builder: (context) => MusicView(
songList: _filteredData, //
initialSongIndex: index, //
),
),
);
}, },
); child: Image.asset('assets/img/More.png'),
}, ),
), onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MusicView(
songList: selectedSongs,
initialSongIndex: index,
onSongStatusChanged:
(index, isCollected, isLiked) {
setState(() {
//
selectedSongs[index].collection =
isCollected;
selectedSongs[index].likes = isLiked;
downloadManager.updateSongInfo(
selectedSongs[index].id,
isCollected,
isLiked);
});
},
),
),
);
},
);
},
), ),
],
),
),
const SizedBox(height: 10,), const SizedBox(
///+ height: 10,
Container( ),
padding: const EdgeInsets.only(left: 20, right: 20, top: 10),
child: const Text(
'每日推荐',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
),
),
const SizedBox(height: 5,),
Container(
padding: const EdgeInsets.only(left: 20, right: 20, top: 5),
height: 186,
width: double.infinity,
child: MySwiperWidget,
),
const SizedBox(height: 10),
/// ///
Container( Container(
alignment: Alignment.topLeft, padding:
padding: const EdgeInsets.only(left: 20, right: 20, top: 5), const EdgeInsets.only(left: 20, right: 20, top: 5),
child: const Text( child: const Text(
'精选歌曲', '精选歌单',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500), style: TextStyle(
), fontSize: 20, fontWeight: FontWeight.w500),
),
const SizedBox(height: 5,),
ListView.builder(
padding: EdgeInsets.zero,
itemCount: selectedSongs.length,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (context, index) {
return ListTile(
leading: Image.network(selectedSongs[index].pic),
title: Text(
selectedSongs[index].title,
style: const TextStyle(fontSize: 18, color: Colors.black),
),
subtitle: Text(
selectedSongs[index].artist,
style: const TextStyle(fontSize: 16, color: Colors.black),
),
trailing: InkWell(
onTap: () {
_bottomSheet(context, index);
},
child: Image.asset('assets/img/More.png'),
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MusicView(
songList: selectedSongs,
initialSongIndex: index,
onSongStatusChanged: (index, isCollected, isLiked) {
setState(() {
//
selectedSongs[index].collection = isCollected;
selectedSongs[index].likes = isLiked;
downloadManager.updateSongInfo(selectedSongs[index].id, isCollected, isLiked);
});
},
),
), ),
); ),
}, const SizedBox(
); height: 5,
}, ),
), SizedBox(
height: 180,
const SizedBox(height: 10,), child: ListView.builder(
/// scrollDirection: Axis.horizontal,
Container( shrinkWrap: true,
padding: const EdgeInsets.only(left: 20, right: 20, top: 5), padding: const EdgeInsets.only(left: 20),
child: const Text( itemCount: homeVM.listArr.length,
'精选歌单', itemBuilder: (context, index) {
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500), var sObj = homeVM.listArr[index];
return ListRow(
sObj: sObj,
onPressed: () {},
onPressedPlay: () {},
);
}),
),
],
),
), ),
), ),
const SizedBox(height: 5,), ),
SizedBox( ],
height: 180,
child: ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
padding: const EdgeInsets.only(left: 20),
itemCount: homeVM.listArr.length,
itemBuilder: (context, index) {
var sObj = homeVM.listArr[index];
return ListRow(
sObj: sObj,
onPressed: () {},
onPressedPlay: () {},
);
}),
),
],
),
), ),
), ),
); );
@ -433,7 +492,8 @@ class _HomeViewState extends State<HomeView> {
shape: const RoundedRectangleBorder( shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(30)), borderRadius: BorderRadius.vertical(top: Radius.circular(30)),
), ),
builder: (context) => StatefulBuilder( // 使StatefulBuilder便 builder: (context) => StatefulBuilder(
// 使StatefulBuilder便
builder: (context, setState) { builder: (context, setState) {
bool likesnot = false; // bool likesnot = false; //
@ -479,11 +539,11 @@ class _HomeViewState extends State<HomeView> {
Column( Column(
children: [ children: [
IconButton( IconButton(
onPressed: (){}, onPressed: () {},
icon: Image.asset("assets/img/list_good.png"), icon: Image.asset("assets/img/list_good.png"),
iconSize: 60, iconSize: 60,
), ),
Text("点赞") const Text("点赞")
], ],
), ),
Column( Column(
@ -492,8 +552,8 @@ class _HomeViewState extends State<HomeView> {
onPressed: () { onPressed: () {
Navigator.pop(context); Navigator.pop(context);
Get.to(() => CommentView( Get.to(() => CommentView(
initialSongIndex: index, initialSongIndex: index,
)); ));
}, },
icon: Image.asset("assets/img/list_comment.png"), icon: Image.asset("assets/img/list_comment.png"),
iconSize: 60, iconSize: 60,

@ -33,6 +33,7 @@ class _MusicViewState extends State<MusicView> with SingleTickerProviderStateMix
AppData appData = AppData(); AppData appData = AppData();
late int currentSongIndex; late int currentSongIndex;
late AudioPlayer _audioPlayer; late AudioPlayer _audioPlayer;
StreamSubscription? _playerStateSubscription;
final downloadManager = Get.put(DownloadManager()); final downloadManager = Get.put(DownloadManager());
@ -69,24 +70,24 @@ class _MusicViewState extends State<MusicView> with SingleTickerProviderStateMix
vsync: this, vsync: this,
); );
// 2. _playerStateSubscription = _audioPlayer.playerStateStream.listen((state) {
_audioPlayer.playerStateStream.listen((state) { if (!_isDisposed) {
if (state.playing) { if (state.playing) {
// _rotationController.repeat();
_rotationController.repeat(); } else {
} else { _rotationController.stop();
// }
_rotationController.stop(canceled: false);
} }
}); });
} }
@override @override
void dispose() { void dispose() {
_isDisposed = true; _isDisposed = true;
_audioPlayer.dispose(); _playerStateSubscription?.cancel();
_rotationController.stop();
_rotationController.dispose(); _rotationController.dispose();
_audioPlayer.dispose();
super.dispose(); super.dispose();
} }
@ -104,6 +105,7 @@ class _MusicViewState extends State<MusicView> with SingleTickerProviderStateMix
} }
Future<void> _updateCurrentSong() async { Future<void> _updateCurrentSong() async {
if (_isDisposed) return;
// UI // UI
setState(() { setState(() {
_isLoading = true; _isLoading = true;
@ -216,14 +218,22 @@ class _MusicViewState extends State<MusicView> with SingleTickerProviderStateMix
} }
void playOrPause() async { void playOrPause() async {
if (_isDisposed) return; //
if (_audioPlayer.playing) { if (_audioPlayer.playing) {
await _audioPlayer.pause(); await _audioPlayer.pause();
_rotationController.stop(canceled: false); if (!_isDisposed) { //
_rotationController.stop();
}
} else { } else {
await _audioPlayer.play(); await _audioPlayer.play();
_rotationController.repeat(); if (!_isDisposed) { //
_rotationController.repeat();
}
}
if (!_isDisposed) {
setState(() {});
} }
setState(() {});
} }
void playNextSong() { void playNextSong() {
@ -605,6 +615,9 @@ class _MusicViewState extends State<MusicView> with SingleTickerProviderStateMix
), ),
), ),
), ),
const SizedBox(
height: 10,
),
Expanded( Expanded(
child: ListView.builder( child: ListView.builder(
itemCount: music.length, itemCount: music.length,
@ -641,21 +654,6 @@ class _MusicViewState extends State<MusicView> with SingleTickerProviderStateMix
}, },
), ),
), ),
ElevatedButton(
onPressed: () => Navigator.pop(context),
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xff429482),
padding: const EdgeInsets.symmetric(vertical: 14),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.zero,
),
),
child: const Text(
"关闭",
style: TextStyle(color: Colors.black, fontSize: 20),
),
),
], ],
), ),
); );

@ -15,7 +15,7 @@ class RankView extends StatefulWidget {
State<RankView> createState() => _RankViewState(); State<RankView> createState() => _RankViewState();
} }
class _RankViewState extends State<RankView> { class _RankViewState extends State<RankView> with AutomaticKeepAliveClientMixin {
final rankVM = Get.put(RankViewModel()); final rankVM = Get.put(RankViewModel());
List rankNames = []; List rankNames = [];
List rankSingerName = []; List rankSingerName = [];
@ -25,42 +25,55 @@ class _RankViewState extends State<RankView> {
final downloadManager = Get.put(DownloadManager()); final downloadManager = Get.put(DownloadManager());
@override
bool get wantKeepAlive => true;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_fetchSonglistData(); _fetchSonglistData();
} }
Future<void> _onRefresh() async {
await _fetchSonglistData();
}
Future<void> _fetchSonglistData() async { Future<void> _fetchSonglistData() async {
RankBean bean2 = await GetRank().getRank(Authorization: AppData().currentToken); try {
setState(() { RankBean bean2 = await GetRank().getRank(Authorization: AppData().currentToken);
rankNames = bean2.data!.map((data) => data.name!).toList(); setState(() {
rankSingerName = bean2.data!.map((data) => data.singerName!).toList(); rankNames = bean2.data!.map((data) => data.name!).toList();
rankCoverPath = bean2.data!.map((data) => data.coverPath!).toList(); rankSingerName = bean2.data!.map((data) => data.singerName!).toList();
rankMusicPath = bean2.data!.map((data) => data.musicPath!).toList(); rankCoverPath = bean2.data!.map((data) => data.coverPath!).toList();
rankMusicPath = bean2.data!.map((data) => data.musicPath!).toList();
if (rankNames.isNotEmpty && if (rankNames.isNotEmpty &&
rankNames.length == rankSingerName.length && rankNames.length == rankSingerName.length &&
rankNames.length == rankCoverPath.length && rankNames.length == rankCoverPath.length &&
rankNames.length == rankMusicPath.length) { rankNames.length == rankMusicPath.length) {
for (int i = 0; i < rankNames.length; i++) { for (int i = 0; i < rankNames.length; i++) {
songs.add(Song( songs.add(Song(
artistPic: rankCoverPath[i], artistPic: rankCoverPath[i],
title: rankNames[i], title: rankNames[i],
artist: rankSingerName[i], artist: rankSingerName[i],
musicurl: rankMusicPath[i], musicurl: rankMusicPath[i],
pic: rankCoverPath[i], pic: rankCoverPath[i],
id: i, id: i,
likes: false, likes: false,
collection: false, collection: false,
)); ));
}
} }
} });
}); } catch (e) {
//
print('Error fetching data: $e');
}
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context);
return Container( return Container(
decoration: const BoxDecoration( decoration: const BoxDecoration(
image: DecorationImage( image: DecorationImage(
@ -74,20 +87,19 @@ class _RankViewState extends State<RankView> {
body: Column( body: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const SizedBox( const SizedBox(height: 40),
height: 40,
),
// //
const Center( const Center(
child: Column( child: Column(
children: [ children: [
SizedBox(
height: 10,
),
Text( Text(
'喵听排行榜', '喵听排行榜',
style: TextStyle(fontSize: 22, fontWeight: FontWeight.w400), style: TextStyle(fontSize: 22, fontWeight: FontWeight.w400),
), ),
SizedBox( SizedBox(height: 10),
height: 10,
),
Text( Text(
'Top50', 'Top50',
style: TextStyle( style: TextStyle(
@ -95,19 +107,15 @@ class _RankViewState extends State<RankView> {
fontSize: 40, fontSize: 40,
fontWeight: FontWeight.w500), fontWeight: FontWeight.w500),
), ),
SizedBox( // SizedBox(height: 10),
height: 10, // Text(
), // '2023/12/12更新 1期',
Text( // style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
'2023/12/12更新 1期', // ),
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
),
], ],
), ),
), ),
const SizedBox( const SizedBox(height: 10),
height: 10,
),
Container( Container(
decoration: const BoxDecoration( decoration: const BoxDecoration(
color: Colors.white, color: Colors.white,
@ -119,7 +127,25 @@ class _RankViewState extends State<RankView> {
child: Row( child: Row(
children: [ children: [
IconButton( IconButton(
onPressed: () {}, onPressed: () {
//
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);
});
},
),
),
);
},
icon: Image.asset( icon: Image.asset(
"assets/img/button_play.png", "assets/img/button_play.png",
width: 20, width: 20,
@ -130,9 +156,7 @@ class _RankViewState extends State<RankView> {
'播放全部', '播放全部',
style: TextStyle(fontSize: 16), style: TextStyle(fontSize: 16),
), ),
const SizedBox( const SizedBox(width: 5),
width: 5,
),
const Text( const Text(
'50', '50',
style: TextStyle(fontSize: 16), style: TextStyle(fontSize: 16),
@ -141,13 +165,16 @@ class _RankViewState extends State<RankView> {
), ),
), ),
Expanded( Expanded(
child: SingleChildScrollView( child: RefreshIndicator(
physics: const BouncingScrollPhysics(), onRefresh: _onRefresh,
child: Container( color: const Color(0xff429482),
color: Colors.white, child: SingleChildScrollView(
child: Column( physics: const AlwaysScrollableScrollPhysics(), //
children: [ child: Container(
ListView.builder( color: Colors.white,
child: Column(
children: [
ListView.builder(
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true, shrinkWrap: true,
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
@ -156,119 +183,107 @@ class _RankViewState extends State<RankView> {
itemBuilder: (context, index) { itemBuilder: (context, index) {
int rankNum = index + 1; int rankNum = index + 1;
return ListTile( return ListTile(
onTap: () { onTap: () {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => MusicView( builder: (context) => MusicView(
songList: songs, songList: songs,
initialSongIndex: index, initialSongIndex: index,
onSongStatusChanged: (index, isCollected, isLiked) { onSongStatusChanged: (index, isCollected, isLiked) {
setState(() { setState(() {
// songs[index].collection = isCollected;
songs[index].collection = isCollected; songs[index].likes = isLiked;
songs[index].likes = isLiked; downloadManager.updateSongInfo(songs[index].id, isCollected, isLiked);
downloadManager.updateSongInfo(songs[index].id, isCollected, isLiked); });
}); },
},
),
), ),
); ),
}, );
title: Column( },
children: [ title: Column(
Row( children: [
children: [ Row(
Row( children: [
mainAxisAlignment: Row(
MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
SizedBox( SizedBox(
width: 25, width: 25,
child: RichText( child: RichText(
text: TextSpan( text: TextSpan(
text: rankNum.toString(), text: rankNum.toString(),
style: const TextStyle( style: const TextStyle(
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
color: Color(0xffCE0000), color: Color(0xffCE0000),
),
), ),
), ),
), ),
), const SizedBox(width: 10),
const SizedBox( ClipRRect(
width: 10, borderRadius: BorderRadius.circular(10),
), child: Image.network(
ClipRRect( rankCoverPath[index],
borderRadius: width: 60,
BorderRadius.circular(10), height: 60,
child: Image.network( fit: BoxFit.cover,
rankCoverPath[index], ),
width: 60,
height: 60,
fit: BoxFit.cover,
), ),
), const SizedBox(width: 20),
const SizedBox( SizedBox(
width: 20, width: 170,
), child: Column(
SizedBox( crossAxisAlignment: CrossAxisAlignment.start,
width: 170, children: [
child: Column( Text(
crossAxisAlignment: rankNames[index],
CrossAxisAlignment.start, maxLines: 1,
children: [ style: const TextStyle(
Text( color: Colors.black,
rankNames[index], fontSize: 16,
maxLines: 1, fontWeight: FontWeight.w400
style: const TextStyle( ),
color: Colors.black, ),
fontSize: 16, Text(
fontWeight: rankSingerName[index],
FontWeight.w400), maxLines: 1,
), style: const TextStyle(
Text( color: Colors.black,
rankSingerName[index], fontSize: 14
maxLines: 1, ),
style: const TextStyle( )
color: Colors.black, ],
fontSize: 14), ),
)
],
), ),
), const SizedBox(width: 18),
const SizedBox( ],
width: 18, ),
), IconButton(
], onPressed: () {
), _bottomSheet(context, index);
IconButton(
onPressed: () {
_bottomSheet(context, index); // index
},
icon: Image.asset(
'assets/img/More.png',
width: 25,
height: 25,
errorBuilder: (context, error, stackTrace) {
print('Error loading image: $error');
return const Icon(Icons.error, size: 25); // 使 const
}, },
icon: Image.asset(
'assets/img/More.png',
width: 25,
height: 25,
errorBuilder: (context, error, stackTrace) {
print('Error loading image: $error');
return const Icon(Icons.error, size: 25);
},
),
), ),
), ],
const SizedBox( ),
height: 20, const SizedBox(height: 10)
) ],
], ),
), );
const SizedBox( },
height: 10, ),
) ],
], ),
));
}),
],
), ),
), ),
), ),
@ -278,12 +293,15 @@ class _RankViewState extends State<RankView> {
), ),
); );
} }
Future _bottomSheet(BuildContext context, int index){
Future _bottomSheet(BuildContext context, int index) {
return showModalBottomSheet( return showModalBottomSheet(
context: context, context: context,
backgroundColor: Colors.white, backgroundColor: Colors.white,
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(30))), shape: const RoundedRectangleBorder(
builder: (context) =>Container( borderRadius: BorderRadius.vertical(top: Radius.circular(30))
),
builder: (context) => Container(
height: 150, height: 150,
padding: const EdgeInsets.only(top: 20), padding: const EdgeInsets.only(top: 20),
child: Column( child: Column(
@ -349,7 +367,6 @@ class _RankViewState extends State<RankView> {
], ],
), ),
) )
); );
} }
} }

@ -23,17 +23,19 @@ class SongInfo {
SongInfo({required this.songName, required this.artistName}); SongInfo({required this.songName, required this.artistName});
} }
class _ReleaseViewState extends State<ReleaseView> { class _ReleaseViewState extends State<ReleaseView> with AutomaticKeepAliveClientMixin {
List<File> coverImages = []; List<File> coverImages = [];
List<SongInfo> songInfoList = []; List<SongInfo> songInfoList = [];
late File selectedMp3File; late File selectedMp3File;
@override
bool get wantKeepAlive => true;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context);
return Scaffold( return Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,

@ -24,7 +24,7 @@ class UserView extends StatefulWidget {
State<UserView> createState() => _UserViewState(); State<UserView> createState() => _UserViewState();
} }
class _UserViewState extends State<UserView> { class _UserViewState extends State<UserView> with AutomaticKeepAliveClientMixin {
final homeVM = Get.put(HomeViewModel()); final homeVM = Get.put(HomeViewModel());
final TextEditingController _controller = TextEditingController(); final TextEditingController _controller = TextEditingController();
int playlistCount = 0; int playlistCount = 0;
@ -36,6 +36,9 @@ class _UserViewState extends State<UserView> {
final downloadManager = Get.put(DownloadManager()); final downloadManager = Get.put(DownloadManager());
@override
bool get wantKeepAlive => true;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@ -61,6 +64,7 @@ class _UserViewState extends State<UserView> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context);
return Container( return Container(
decoration: const BoxDecoration( decoration: const BoxDecoration(
image: DecorationImage( image: DecorationImage(
@ -123,7 +127,12 @@ class _UserViewState extends State<UserView> {
children: [ children: [
InkWell( InkWell(
onTap: () { onTap: () {
Get.to(const MyMusicView()); Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const MyMusicView(),
),
);
}, },
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -159,7 +168,12 @@ class _UserViewState extends State<UserView> {
// //
InkWell( InkWell(
onTap: () async { onTap: () async {
final result = await Get.to(const MyDownloadView()); final result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MyDownloadView(),
),
);
if (result == true) { if (result == true) {
setState(() { setState(() {
@ -252,7 +266,14 @@ class _UserViewState extends State<UserView> {
InkWell( InkWell(
onTap: () { onTap: () {
print('点击成功'); print('点击成功');
Get.to(MyMusicView(songlistIdd: playlistid[index])); Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MyMusicView(
songlistIdd: playlistid[index]
),
),
);
}, },
child: Row( child: Row(
children: [ children: [
@ -304,7 +325,12 @@ class _UserViewState extends State<UserView> {
children: [ children: [
InkWell( InkWell(
onTap: () { onTap: () {
Get.to(const MyWorkView()); Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const MyWorkView(),
),
);
}, },
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -365,7 +391,12 @@ class _UserViewState extends State<UserView> {
IconButton( IconButton(
onPressed: () async { onPressed: () async {
Navigator.pop(context); Navigator.pop(context);
bool result = await Get.to(const UserInfo()); bool result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const UserInfo(),
),
);
if (result) { if (result) {
setState(() { setState(() {
avatar = AppData().currentAvatar; avatar = AppData().currentAvatar;

Loading…
Cancel
Save