import 'package:flutter/material.dart'; import 'package:flutter_swiper_view/flutter_swiper_view.dart'; import 'package:get/get.dart'; import 'package:music_player_miao/api/api_music_return.dart'; import 'package:music_player_miao/common_widget/app_data.dart'; import 'package:music_player_miao/models/search_bean.dart'; import 'package:music_player_miao/view/commend_view.dart'; import '../../view_model/home_view_model.dart'; import '../api/api_music_list.dart'; import '../common/download_manager.dart'; import '../common_widget/Song_widegt.dart'; import '../common_widget/list_cell.dart'; import '../models/getMusicList_bean.dart'; import 'music_view.dart'; class HomeView extends StatefulWidget { const HomeView({super.key}); @override State createState() => _HomeViewState(); } class _HomeViewState extends State { // 使用 GetX 框架的依赖注入,将 HomeViewModel 实例注册为 homeVM。 // Get.put() 方法会创建 HomeViewModel 的实例,并将其保存在 GetX 的依赖管理器中,方便后续使用。 final homeVM = Get.put(HomeViewModel()); // 创建一个 TextEditingController,用于控制和监听搜索输入框的文本变化。 // 这个控制器可以用于获取输入框的内容、清空输入框等操作。 final TextEditingController _controller = TextEditingController(); // 定义一个布尔变量 _isSearching,用于表示当前是否处于搜索状态。 // 当用户在搜索框中输入内容时,_isSearching 会变为 true;当输入框为空时,_isSearching 会变为 false。 bool _isSearching = false; final downloadManager = Get.put(DownloadManager()); void initState() { super.initState(); _fetchSonglistData(); } List selectedSongs = []; Future _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!), ]; }); } ///轮播图 List imgList = [ {"image": "assets/img/banner.png"}, {"image": "assets/img/banner.png"}, {"image": "assets/img/banner.png"}, ]; List _filteredData = []; Future _filterData(String query) async { if (query.isNotEmpty) { try { // 发起搜索请求 SearchBean bean = await SearchMusic().search( keyword: query, Authorization: AppData().currentToken, ); // 如果请求成功且返回的数据不为空 if (bean.code == 200 && bean.data != null) { // 创建一个临时列表来存储所有异步请求 List> songDetailsFutures = []; // 循环处理每个搜索结果,通过 id 请求详细信息 for (var data in bean.data!) { 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 }) ); } else { print("Song ID is null for song: ${data.name}"); } } // 使用 Future.wait 等待所有异步请求完成 List songDetailsList = await Future.wait(songDetailsFutures); // 过滤掉 null 值 List validSongDetails = songDetailsList.where((song) => song != null).cast().toList(); // 最后更新 UI,一次性更新 _filteredData setState(() { _filteredData = validSongDetails; // 更新搜索结果 _isSearching = true; // 设置正在搜索中 }); // 打印最终结果 print("Filtered Data: $_filteredData"); } else { setState(() { _filteredData = []; _isSearching = false; }); } } catch (error) { print("Error occurred during search: $error"); setState(() { _filteredData = []; _isSearching = false; }); } } else { setState(() { _filteredData = []; _isSearching = false; }); } } @override Widget build(BuildContext context) { ///轮播图 var MySwiperWidget = Swiper( itemBuilder: (BuildContext context, int index) { //每次循环遍历时,将i赋值给index return new Image.asset( imgList[index]['image'], fit: BoxFit.fill, ); }, itemCount: imgList.length, //指示器 pagination: SwiperPagination( builder: DotSwiperPaginationBuilder( color: Colors.white.withOpacity(0.85), // Color of inactive dots activeColor: const Color(0xff429482), // Color of active dot ), ), // autoplay: true, autoplayDelay: 3000, ); 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: 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, ), Text( '你的云端音乐库', style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500), ), ], ), ), const SizedBox(height: 10,), ///搜索 Container( padding: const EdgeInsets.only(left: 20, right: 20, top: 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, ) ], ), 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, ), ), ), ), if (_isSearching) Container( height: 150, width: 345, decoration: BoxDecoration( color: const Color(0xffF9F2AF).withOpacity(0.7), ), 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, // 传递当前歌曲在歌曲列表中的索引,用于在新页面中显示或操作 ), ), ); }, ); }, ), ), ], ), ), 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( 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); }); }, ), ), ); }, ); }, ), 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: () {}, ); }), ), ], ), ), ), ); } 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) => StatefulBuilder( // 使用StatefulBuilder以便动态修改状态 builder: (context, setState) { bool likesnot = false; // 初始状态,假设未点赞 return Container( height: 150, padding: const EdgeInsets.only(top: 20), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Column( children: [ IconButton( onPressed: () {}, icon: Image.asset("assets/img/list_add.png"), iconSize: 60, ), const Text("加入歌单"), ], ), Column( children: [ IconButton( onPressed: () {}, icon: Image.asset("assets/img/list_download.png"), iconSize: 60, ), const Text("下载"), ], ), Column( children: [ IconButton( onPressed: () {}, icon: Image.asset("assets/img/list_collection.png"), iconSize: 60, ), const Text("收藏"), ], ), Column( children: [ IconButton( onPressed: (){}, icon: Image.asset("assets/img/list_good.png"), iconSize: 60, ), Text("点赞") ], ), Column( children: [ IconButton( onPressed: () { Navigator.pop(context); Get.to(() => CommentView( initialSongIndex: index, )); }, icon: Image.asset("assets/img/list_comment.png"), iconSize: 60, ), const Text("评论"), ], ), ], ), ], ), ); }, ), ); } }