import 'dart:async'; import 'package:aiplot/tools/gallery/gallery_content_model.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; import '../../bean/gallery_label_bean.dart'; import '../../bean/gallery_work_label_bean.dart'; import '../../bean/gallery_work_list_bean.dart'; import '../../bean/recommender_bean.dart'; import '../../common/Global.dart'; import '../../common/dialog_bean.dart'; import '../../common/dialog_manager.dart'; import '../../common/dialog_util.dart'; import '../../common/func.dart'; import '../../dialog/login_dialog.dart'; import '../../dialog/phone_login_dialog.dart'; import '../../generated/l10n.dart'; import '../../network/NetworkConfig.dart'; import '../drawdetails/expert_user_details_page.dart'; import '../drawdetails/influential_details_page.dart'; class GalleryContentPage extends StatefulWidget { GalleryContentPage({Key? key}) : super(key: key); @override State createState() => _GalleryContentPageState(); } class _GalleryContentPageState extends State with SingleTickerProviderStateMixin { StreamSubscription? subscription; final GalleryContentModel _viewModel = GalleryContentModel(); GlobalKey loginDialogKey = GlobalKey(); //登录弹框key final ScrollController _scrollController = ScrollController(); TabController? tabController; List labelList = []; List myTabs = []; String influentialCode = ""; List recommenderList = []; List workLabelList = []; int currentLabelIndex = 0; //当前选中标签 int currentChild = 1; //当前选中的子标签 List galleryList = []; int index = 1; //当前页数 FocusNode focusNode = FocusNode(); //创建StreamController StreamController? streamController; // 获取StreamSink用于发射事件 StreamSink? get streamSink => streamController?.sink; // 获取Stream用于监听 Stream? get streamData => streamController?.stream; void influentialChange(String str) { influentialCode = str.toUpperCase(); } void getWorksListByLabel(bool isLoad) { EasyLoading.show(status: 'loading...'); _viewModel.getWorksListByLabel(workLabelList[currentLabelIndex].LabelId, currentChild, index, isLoad); } @override void initState() { // TODO: implement initState super.initState(); streamController = StreamController(); //网络请求回调 subscription = _viewModel.streamController.stream.listen((newData) { String code = newData['code']; if (code.isNotEmpty) { EasyLoading.dismiss(); switch (code) { case "getRecommenderList": recommenderList = newData['data']; break; case "getGalleryWorkLabel": workLabelList = newData['data']; getWorksListByLabel(false); break; case "getWorksListByLabel": if (newData['isLoad']) { galleryList.addAll(newData['data']); } else { galleryList = newData['data']; } break; case "getUserHomePageByPw": //搜索达人 Navigator.push( context, MaterialPageRoute( builder: (context) => ExpertUserDetailsPage( workUserId: "${newData['data']}", worksID: '0', ), )); break; default: String message = newData['data']; EasyLoading.showToast(message); break; } setState(() {}); } }); //上拉加载 _scrollController.addListener(() { //判断是否滑动到了页面的最底部 if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) { //如果不是最后一页数据,则生成新的数据添加到list里面 index++; getWorksListByLabel(true); } ///置顶按钮 if (_scrollController.position.pixels > 600) { streamSink?.add(true); } else { streamSink?.add(false); } }); _viewModel.getRecommenderList(); _viewModel.getGalleryWorkLabel(); } @override void dispose() { // TODO: implement dispose subscription?.cancel(); streamController?.close(); tabController?.dispose(); focusNode.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final size = MediaQuery.of(context).size; return Scaffold( backgroundColor: Colors.white, appBar: AppBar( backgroundColor: Colors.white, elevation: 0, title: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( margin: const EdgeInsets.only(right: 10), child: const Image( width: 23, height: 23, image: AssetImage('assets/images/ic_title.png'), ), ), Text( "AI${S.of(context).Gallery}", style: const TextStyle(color: Colors.black, fontSize: 20), ), ], ), centerTitle: true, ), body: RefreshIndicator( onRefresh: _onRefresh, child: Stack( children: [ SingleChildScrollView( controller: _scrollController, child: Container( margin: const EdgeInsets.only(left: 15), child: Column( children: [ ///搜索达人 Container( margin: const EdgeInsets.only(right: 15), child: Container( width: double.infinity, height: 40, decoration: BoxDecoration( border: Border.all(width: 1, color: const Color(0xFF8841FF)), borderRadius: const BorderRadius.all(Radius.circular(20)), ), child: Stack( alignment: Alignment.center, children: [ const Positioned( left: 17, child: Image( image: AssetImage('assets/images/ic_search.png'), width: 19, height: 19, )), Positioned( left: 47, right: 70, child: Container( height: 30, width: double.infinity, alignment: Alignment.centerLeft, child: TextField( keyboardType: TextInputType.text, focusNode: focusNode, decoration: InputDecoration( hintText: S.of(context).Search_influential, hintStyle: const TextStyle(fontSize: 14, color: Color(0xFF999999)), border: InputBorder.none, isCollapsed: true, ), onChanged: influentialChange, ), ), ), Positioned( right: 7, child: GestureDetector( onTap: () { if (NetworkConfig.userId == "") { showLoginDialog(); } else { if (influentialCode != "") { focusNode.unfocus(); _viewModel.getUserHomePageByPw(influentialCode); } } }, child: Container( width: 60, height: 28, alignment: Alignment.center, decoration: BoxDecoration(color: const Color(0xFF8841FF), borderRadius: BorderRadius.circular(14)), child: Text( S.of(context).search, style: const TextStyle(color: Colors.white, fontSize: 14), ), ), )), ], ), ), ), ///推荐达人 recommenderList.isNotEmpty ? Container( alignment: Alignment.centerLeft, margin: const EdgeInsets.only(top: 20), child: Text( S.of(context).Recommended_influencers, style: const TextStyle(fontSize: 16, color: Colors.black, fontWeight: FontWeight.w600), ), ) : Container(), recommenderList.isNotEmpty ? Container( height: 70, alignment: Alignment.centerLeft, margin: const EdgeInsets.only(top: 20, right: 15), child: ListView.builder( shrinkWrap: true, itemCount: recommenderList.length, itemBuilder: (context, index) { return influential(recommenderList[index]); }, scrollDirection: Axis.horizontal), ) : Container(), ///作品展示 Container( alignment: Alignment.centerLeft, margin: const EdgeInsets.only(top: 20), child: Text( S.of(context).Exhibition_works, style: const TextStyle(fontSize: 16, color: Colors.black, fontWeight: FontWeight.w600), ), ), ///标签 Container( height: 25, alignment: Alignment.center, margin: const EdgeInsets.only(top: 12), child: ListView.builder( itemCount: workLabelList.length, itemBuilder: (context, index) { return _labelItem(workLabelList[index], index); }, scrollDirection: Axis.horizontal, ), ), ///子标签 Container( margin: const EdgeInsets.only(top: 11), child: Row( children: [ GestureDetector( onTap: () { currentChild = 1; getWorksListByLabel(false); }, child: Container( margin: const EdgeInsets.only(right: 10), child: Text( S.of(context).Newest, style: TextStyle(color: currentChild == 1 ? Colors.black : Color(0xFF999999)), ), ), ), GestureDetector( onTap: () { currentChild = 2; getWorksListByLabel(false); }, child: Container( margin: EdgeInsets.only(right: 10), child: Text( S.of(context).Popular, style: TextStyle(color: currentChild == 2 ? Colors.black : Color(0xFF999999)), ), ), ), GestureDetector( onTap: () { currentChild = 3; getWorksListByLabel(false); }, child: Container( margin: EdgeInsets.only(right: 10), child: Text( S.of(context).all, style: TextStyle(color: currentChild == 3 ? Colors.black : Color(0xFF999999)), ), ), ), ], ), ), Container( margin: EdgeInsets.only(top: 16, right: 15), child: MasonryGridView.count( crossAxisCount: 2, itemCount: galleryList.length, itemBuilder: (BuildContext context, int index) { return _galleryItem(galleryList[index], index); }, shrinkWrap: true, // 纵向元素间距 mainAxisSpacing: 0, // 横向元素间距 crossAxisSpacing: 10, physics: const NeverScrollableScrollPhysics(), ), ), ], ), ), ), ///置顶 StreamBuilder( stream: streamData, builder: (BuildContext context, AsyncSnapshot snapshot) { if (snapshot.data != null && snapshot.data) { return Positioned( right: 10, bottom: 50, child: GestureDetector( onTap: () { _scrollController.animateTo(0, duration: Duration(milliseconds: 500), curve: Curves.decelerate); }, child: const Image( width: 60, image: AssetImage('assets/images/ic_topping.png'), ), ), ); } else { return Container(); } }), ], ), ), ); } // 下拉刷新 Future _onRefresh() async { // 持续两秒 await Future.delayed(const Duration(milliseconds: 1500), () { currentLabelIndex = 0; currentChild = 1; index = 1; galleryList = []; _viewModel.getRecommenderList(); _viewModel.getGalleryWorkLabel(); }); } //达人条目 influential(RecommenderBean data) { return GestureDetector( onTap: () { if (NetworkConfig.userId == "") { showLoginDialog(); } else { focusNode.unfocus(); Navigator.push( context, MaterialPageRoute( builder: (context) => ExpertUserDetailsPage( workUserId: "${data.UserId}", worksID: '${data.UserFollow}', ), )); } }, child: Container( width: 50, margin: EdgeInsets.only(right: 10), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ ClipOval( child: CachedNetworkImage( width: 50, height: 50, imageUrl: data.UserIconUrl!, errorWidget: (context, url, error) => Icon(Icons.error), ), ), SizedBox( width: 50, child: Text( "${data.NickName}", style: TextStyle(fontSize: 12, color: Color(0xFF999999)), overflow: TextOverflow.ellipsis, ), ) ], ), )); } //作品标签 _labelItem(GalleryWorkLabelBean data, index) { return GestureDetector( onTap: () { if (NetworkConfig.userId == "") { showLoginDialog(); } else { focusNode.unfocus(); currentLabelIndex = index; currentChild = 1; getWorksListByLabel(false); setState(() {}); } }, child: Container( padding: const EdgeInsets.only(left: 10, right: 10), alignment: Alignment.center, decoration: BoxDecoration( color: Color(currentLabelIndex == index ? 0xFF8841FF : 0xFFF6F7FF), borderRadius: const BorderRadius.all(Radius.circular(20)), ), margin: const EdgeInsets.only(right: 12), child: Text( "${data.LabelName}", style: TextStyle(color: currentLabelIndex == index ? Colors.white : Color(0xFF999999), fontSize: 13), ), ), ); } //画廊 _galleryItem(GalleryWorkListBean bean, int index) { return Column( children: [ ///Ai图 ClipRRect( borderRadius: BorderRadius.circular(7), child: GestureDetector( onTap: () { focusNode.unfocus(); if (NetworkConfig.userId == "") { showLoginDialog(); } else { // Navigator.push( // context, // MaterialPageRoute( // builder: (context) => DrawDetailsPage( // false, // drawId: bean.DrawId.toString(), // isMyWork: false, // status: 3, // ), // )); Navigator.push( context, MaterialPageRoute( builder: (context) => InfluentialDetailsPage(bean.DrawId.toString()), )); } }, child: Stack( children: [ CachedNetworkImage( imageUrl: bean.ImageUrl!, errorWidget: (context, url, error) => Icon(Icons.error), ), bean.IsTalent == 1 ? const Positioned( left: 6, top: 6, child: Image( width: 42, image: AssetImage('assets/images/ic_portfolio.webp'), )) : Container(), ], ), ), ), Row( children: [ bean.IsTalent == 1 ? Container( width: 48, height: 15, alignment: Alignment.center, margin: EdgeInsets.only(top: 2), decoration: BoxDecoration( border: Border.all(color: Color(0xFFFF6316), width: 1), borderRadius: BorderRadius.all(Radius.circular(3)), ), child: Text( S.of(context).Expert_selection, style: TextStyle(fontSize: 10, color: Color(0xFFFF661B)), ), ) : Container(), Container( width: bean.IsTalent == 1 ? 100 : 140, alignment: Alignment.centerLeft, margin: EdgeInsets.only(left: 5), child: Text( "${bean.Title}", maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(color: Colors.black), ), ), ], ), Container( height: 25, margin: EdgeInsets.only(bottom: 10), child: Stack( alignment: Alignment.center, children: [ ///头像 Positioned( left: 0, child: ClipOval( child: CachedNetworkImage( fit: BoxFit.fitHeight, width: 18, height: 18, imageUrl: bean.UserIocn!, errorWidget: (context, url, error) => Image( fit: BoxFit.fitWidth, width: 18, height: 18, image: AssetImage('assets/images/head.png'), ), ), ), ), Positioned( left: 23, child: Container( width: 80, child: Text( bean.UserNickName!, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(color: Colors.black, fontSize: 12), ), ), ), ///点赞收藏 Positioned( right: 0, child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { focusNode.unfocus(); if (NetworkConfig.userId == "") { showLoginDialog(); } else { if (NetworkConfig.userId != "${bean.UserId}") { bean.IsCollect = !bean.IsCollect!; if (bean.IsCollect!) { bean.LikeNum = (bean.LikeNum! + 1); } else { if (bean.LikeNum! > 0) { bean.LikeNum = (bean.LikeNum! - 1); } } setState(() {}); } _viewModel.userDrawCollect(bean.IsCollect!, bean.DrawId.toString()); } }, child: Container( padding: EdgeInsets.all(15), child: Row( children: [ Image( width: 13, height: 12, image: bean.IsCollect! ? const AssetImage('assets/images/ic_collect_s.png') : const AssetImage('assets/images/ic_collect.png'), ), Container( margin: EdgeInsets.only(left: 5), child: Text( bean.LikeNum.toString(), style: TextStyle(color: bean.IsCollect! ? Color(0xFFBB72E0) : Colors.black, fontSize: 12), ), ) ], ), )), ), ], ), ), ], ); } //弹出登录 showLoginDialog() { DialogManager() ..add(DialogBean( dialogPriority: DialogPriority.highClear, createDialogWidget: () => DialogUtil.createTipWidget( context, LoginDialog( loginDialogKey, onTap: (index) { switch (index) { case 0: if (loginDialogKey.currentState != null) { loginDialogKey.currentState!.Pop(); } FunctionUtil.bottomSheetDialog(context, PhoneLoginDialog()); break; case 1: //谷歌登录 Map map = {"googleLogin": "googleLogin"}; invokeNativeMethod("googleLogin", map); break; } }, ), "LoginDialog", canceled: true))) ..show(context); } // 获取原生的值 invokeNativeMethod(String method, Map map) async { dynamic args; try { args = await Global.method.invokeMethod(method, map); } on PlatformException catch (e) {} } }