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

chen
Spark 3 months ago
parent fc613ee961
commit 38921f848f

@ -20,67 +20,77 @@ class HomeView extends StatefulWidget {
State<HomeView> createState() => _HomeViewState();
}
class _HomeViewState extends State<HomeView> {
// 使 GetX HomeViewModel homeVM
// Get.put() HomeViewModel GetX 便使
class _HomeViewState extends State<HomeView>
with AutomaticKeepAliveClientMixin {
final homeVM = Get.put(HomeViewModel());
// TextEditingController
//
final TextEditingController _controller = TextEditingController();
// _isSearching
// _isSearching true_isSearching false
bool _isSearching = false;
final downloadManager = Get.put(DownloadManager());
List<Song> selectedSongs = [];
@override
bool get wantKeepAlive => true;
@override
void initState() {
super.initState();
_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(() {
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!),
];
});
Future<void> _onRefresh() async {
try {
//
await _fetchSonglistData();
} catch (e) {
print('Refresh error: $e');
//
}
}
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 = [
@ -107,32 +117,40 @@ class _HomeViewState extends State<HomeView> {
// id
for (var data in bean.data!) {
if (data.id != null) { // id null
if (data.id != null) {
// id null
// 使 id Future
songDetailsFutures.add(
GetMusicDetail().getMusicDetail(
songId: data.id!,
Authorization: AppData().currentToken,
).then((details) {
if (details != null) {
// Song
return Song(
artistPic: details.artistPic ?? '', //
title: data.name ?? '', //
artist: details.artist ?? '', //
musicurl: details.musicurl ?? '', //
pic: details.pic ?? '', //
id: details.id, // ID
likes: details.likes, //
collection: details.collection, //
);
}
return null; // null
}).catchError((error) {
print("Error occurred while fetching song details: $error");
return null; // null
})
);
songDetailsFutures.add(GetMusicDetail()
.getMusicDetail(
songId: data.id!,
Authorization: AppData().currentToken,
)
.then((details) {
if (details != null) {
// Song
return Song(
artistPic: details.artistPic ?? '',
//
title: data.name ?? '',
//
artist: details.artist ?? '',
//
musicurl: details.musicurl ?? '',
//
pic: details.pic ?? '',
//
id: details.id,
// ID
likes: details.likes,
//
collection: details.collection, //
);
}
return null; // null
}).catchError((error) {
print("Error occurred while fetching song details: $error");
return null; // null
}));
} else {
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);
// 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
setState(() {
_filteredData = validSongDetails; //
_isSearching = true; //
_filteredData = validSongDetails; //
_isSearching = true; //
});
//
@ -175,6 +196,8 @@ class _HomeViewState extends State<HomeView> {
@override
Widget build(BuildContext context) {
super.build(context);
///
var MySwiperWidget = Swiper(
itemBuilder: (BuildContext context, int index) {
@ -205,222 +228,258 @@ class _HomeViewState extends State<HomeView> {
child: Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Colors.transparent,
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
///
Container(
padding: const EdgeInsets.only(left: 20, top: 50),
child: const Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
'喵听',
style:
TextStyle(fontSize: 35, fontWeight: FontWeight.bold),
),
SizedBox(
width: 10,
body: Column(
children: [
///
Container(
padding: const EdgeInsets.only(left: 20, top: 50),
child: const Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
'喵听',
style: TextStyle(fontSize: 35, fontWeight: FontWeight.bold),
),
SizedBox(width: 10),
Text(
'你的云端音乐库',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
),
],
),
),
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(
'你的云端音乐库',
style:
TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
child: TextField(
controller: _controller,
onChanged: (query) {
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,
),
),
),
],
),
),
const SizedBox(height: 10,),
///
Container(
padding: const EdgeInsets.only(left: 20, right: 20, top: 10),
child: Column(
children: [
),
if (_isSearching)
Container(
height: 38,
height: 150,
width: 345,
decoration: BoxDecoration(
color: const Color(0xffF9F2AF),
borderRadius: BorderRadius.circular(19),
boxShadow: const [
BoxShadow(
color: Colors.black26,
offset: Offset(0, 1),
blurRadius: 0.1,
)
],
color: const Color(0xffF9F2AF).withOpacity(0.7),
),
child: TextField(
controller: _controller,
onChanged: (query) {
setState(() async {
_filterData(query);
});
child: ListView.builder(
padding: EdgeInsets.zero,
itemCount: _filteredData.length,
itemBuilder: (context, index) {
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(
height: 150,
width: 345,
decoration: BoxDecoration(
color: const Color(0xffF9F2AF).withOpacity(0.7),
padding:
const EdgeInsets.only(left: 20, right: 20, top: 10),
child: const Text(
'每日推荐',
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.w500),
),
child: ListView.builder(
padding: EdgeInsets.zero,
itemCount: _filteredData.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_filteredData[index].title),
),
const SizedBox(height: 5),
Container(
padding: const EdgeInsets.symmetric(
horizontal: 20, vertical: 5),
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: () {
//
Navigator.push(
// 使 Navigator
context,
MaterialPageRoute(
// MusicView
builder: (context) => MusicView(
songList: _filteredData, //
initialSongIndex: index, //
),
),
);
_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: 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),
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: () {
_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);
});
},
),
///
Container(
padding:
const EdgeInsets.only(left: 20, right: 20, top: 5),
child: const Text(
'精选歌单',
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.w500),
),
);
},
);
},
),
const SizedBox(height: 10,),
///
Container(
padding: const EdgeInsets.only(left: 20, right: 20, top: 5),
child: const Text(
'精选歌单',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
),
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: () {},
);
}),
),
],
),
),
),
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(
borderRadius: BorderRadius.vertical(top: Radius.circular(30)),
),
builder: (context) => StatefulBuilder( // 使StatefulBuilder便
builder: (context) => StatefulBuilder(
// 使StatefulBuilder便
builder: (context, setState) {
bool likesnot = false; //
@ -479,11 +539,11 @@ class _HomeViewState extends State<HomeView> {
Column(
children: [
IconButton(
onPressed: (){},
onPressed: () {},
icon: Image.asset("assets/img/list_good.png"),
iconSize: 60,
),
Text("点赞")
const Text("点赞")
],
),
Column(
@ -492,8 +552,8 @@ class _HomeViewState extends State<HomeView> {
onPressed: () {
Navigator.pop(context);
Get.to(() => CommentView(
initialSongIndex: index,
));
initialSongIndex: index,
));
},
icon: Image.asset("assets/img/list_comment.png"),
iconSize: 60,

@ -33,6 +33,7 @@ class _MusicViewState extends State<MusicView> with SingleTickerProviderStateMix
AppData appData = AppData();
late int currentSongIndex;
late AudioPlayer _audioPlayer;
StreamSubscription? _playerStateSubscription;
final downloadManager = Get.put(DownloadManager());
@ -69,24 +70,24 @@ class _MusicViewState extends State<MusicView> with SingleTickerProviderStateMix
vsync: this,
);
// 2.
_audioPlayer.playerStateStream.listen((state) {
if (state.playing) {
//
_rotationController.repeat();
} else {
//
_rotationController.stop(canceled: false);
_playerStateSubscription = _audioPlayer.playerStateStream.listen((state) {
if (!_isDisposed) {
if (state.playing) {
_rotationController.repeat();
} else {
_rotationController.stop();
}
}
});
}
@override
void dispose() {
_isDisposed = true;
_audioPlayer.dispose();
_playerStateSubscription?.cancel();
_rotationController.stop();
_rotationController.dispose();
_audioPlayer.dispose();
super.dispose();
}
@ -104,6 +105,7 @@ class _MusicViewState extends State<MusicView> with SingleTickerProviderStateMix
}
Future<void> _updateCurrentSong() async {
if (_isDisposed) return;
// UI
setState(() {
_isLoading = true;
@ -216,14 +218,22 @@ class _MusicViewState extends State<MusicView> with SingleTickerProviderStateMix
}
void playOrPause() async {
if (_isDisposed) return; //
if (_audioPlayer.playing) {
await _audioPlayer.pause();
_rotationController.stop(canceled: false);
if (!_isDisposed) { //
_rotationController.stop();
}
} else {
await _audioPlayer.play();
_rotationController.repeat();
if (!_isDisposed) { //
_rotationController.repeat();
}
}
if (!_isDisposed) {
setState(() {});
}
setState(() {});
}
void playNextSong() {
@ -605,6 +615,9 @@ class _MusicViewState extends State<MusicView> with SingleTickerProviderStateMix
),
),
),
const SizedBox(
height: 10,
),
Expanded(
child: ListView.builder(
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();
}
class _RankViewState extends State<RankView> {
class _RankViewState extends State<RankView> with AutomaticKeepAliveClientMixin {
final rankVM = Get.put(RankViewModel());
List rankNames = [];
List rankSingerName = [];
@ -25,42 +25,55 @@ class _RankViewState extends State<RankView> {
final downloadManager = Get.put(DownloadManager());
@override
bool get wantKeepAlive => true;
@override
void initState() {
super.initState();
_fetchSonglistData();
}
Future<void> _onRefresh() async {
await _fetchSonglistData();
}
Future<void> _fetchSonglistData() async {
RankBean bean2 = await GetRank().getRank(Authorization: AppData().currentToken);
setState(() {
rankNames = bean2.data!.map((data) => data.name!).toList();
rankSingerName = bean2.data!.map((data) => data.singerName!).toList();
rankCoverPath = bean2.data!.map((data) => data.coverPath!).toList();
rankMusicPath = bean2.data!.map((data) => data.musicPath!).toList();
try {
RankBean bean2 = await GetRank().getRank(Authorization: AppData().currentToken);
setState(() {
rankNames = bean2.data!.map((data) => data.name!).toList();
rankSingerName = bean2.data!.map((data) => data.singerName!).toList();
rankCoverPath = bean2.data!.map((data) => data.coverPath!).toList();
rankMusicPath = bean2.data!.map((data) => data.musicPath!).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: i,
likes: false,
collection: false,
));
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: i,
likes: false,
collection: false,
));
}
}
}
});
});
} catch (e) {
//
print('Error fetching data: $e');
}
}
@override
Widget build(BuildContext context) {
super.build(context);
return Container(
decoration: const BoxDecoration(
image: DecorationImage(
@ -74,20 +87,19 @@ class _RankViewState extends State<RankView> {
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 40,
),
const SizedBox(height: 40),
//
const Center(
child: Column(
children: [
SizedBox(
height: 10,
),
Text(
'喵听排行榜',
style: TextStyle(fontSize: 22, fontWeight: FontWeight.w400),
),
SizedBox(
height: 10,
),
SizedBox(height: 10),
Text(
'Top50',
style: TextStyle(
@ -95,19 +107,15 @@ class _RankViewState extends State<RankView> {
fontSize: 40,
fontWeight: FontWeight.w500),
),
SizedBox(
height: 10,
),
Text(
'2023/12/12更新 1期',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
),
// SizedBox(height: 10),
// Text(
// '2023/12/12更新 1期',
// style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
// ),
],
),
),
const SizedBox(
height: 10,
),
const SizedBox(height: 10),
Container(
decoration: const BoxDecoration(
color: Colors.white,
@ -119,7 +127,25 @@ class _RankViewState extends State<RankView> {
child: Row(
children: [
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(
"assets/img/button_play.png",
width: 20,
@ -130,9 +156,7 @@ class _RankViewState extends State<RankView> {
'播放全部',
style: TextStyle(fontSize: 16),
),
const SizedBox(
width: 5,
),
const SizedBox(width: 5),
const Text(
'50',
style: TextStyle(fontSize: 16),
@ -141,13 +165,16 @@ class _RankViewState extends State<RankView> {
),
),
Expanded(
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Container(
color: Colors.white,
child: Column(
children: [
ListView.builder(
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(
@ -156,119 +183,107 @@ class _RankViewState extends State<RankView> {
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);
});
},
),
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),
),
);
},
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,
),
ClipRRect(
borderRadius:
BorderRadius.circular(10),
child: Image.network(
rankCoverPath[index],
width: 60,
height: 60,
fit: BoxFit.cover,
const SizedBox(width: 10),
ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Image.network(
rankCoverPath[index],
width: 60,
height: 60,
fit: BoxFit.cover,
),
),
),
const SizedBox(
width: 20,
),
SizedBox(
width: 170,
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
rankNames[index],
maxLines: 1,
style: const TextStyle(
color: Colors.black,
fontSize: 16,
fontWeight:
FontWeight.w400),
),
Text(
rankSingerName[index],
maxLines: 1,
style: const TextStyle(
color: Colors.black,
fontSize: 14),
)
],
const SizedBox(width: 20),
SizedBox(
width: 170,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
rankNames[index],
maxLines: 1,
style: const TextStyle(
color: Colors.black,
fontSize: 16,
fontWeight: FontWeight.w400
),
),
Text(
rankSingerName[index],
maxLines: 1,
style: const TextStyle(
color: Colors.black,
fontSize: 14
),
)
],
),
),
),
const SizedBox(
width: 18,
),
],
),
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
const SizedBox(width: 18),
],
),
IconButton(
onPressed: () {
_bottomSheet(context, 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 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(
context: context,
backgroundColor: Colors.white,
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(30))),
builder: (context) =>Container(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(30))
),
builder: (context) => Container(
height: 150,
padding: const EdgeInsets.only(top: 20),
child: Column(
@ -349,7 +367,6 @@ class _RankViewState extends State<RankView> {
],
),
)
);
}
}
}

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

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

Loading…
Cancel
Save