import 'dart:math'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:circle_app/app/circle/widgets/info_list_view.dart'; import 'package:circle_app/app/dialog/ScreenBottomSheetDialog.dart'; import 'package:circle_app/router/app_routers.dart'; import 'package:circle_app/util/util.dart'; import 'package:flutter/material.dart'; import 'package:flutter_pickers/pickers.dart'; import 'package:flutter_pickers/style/default_style.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_swiper/flutter_swiper.dart'; import 'package:get/get.dart'; import 'package:pull_to_refresh/pull_to_refresh.dart'; import '../../util/eventBus.dart'; import '../select_circle/logic.dart'; import '../userinfo/logic.dart'; import 'logic.dart'; class CirclePage extends StatefulWidget { CirclePage({Key? key}) : super(key: key); @override State createState() => _CirclePageState(); } class _CirclePageState extends State with SingleTickerProviderStateMixin { late TabController _tabController; late PageController _pageController; @override bool get wantKeepAlive => true; @override void initState() { super.initState(); _pageController = PageController(); _tabController = TabController(length: 2, vsync: this); _tabController.addListener(_handleTabChange); } void _handleTabChange() { // 在这里可以执行滑动监听后的逻辑操作 // 比如根据当前选中的标签执行其他操作 // int currentIndex = .toString()); logic.isShowCircle = _tabController.index == 0; logic.update(); } // 是否需要缓存 final logic = Get.put(CircleLogic()); final state = Get.find().state; var getContext; @override void dispose() { _tabController.removeListener(_handleTabChange); // 移除监听 _tabController.dispose(); _pageController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { getContext = context; return GetBuilder(builder: (logic) { return Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, decoration: BoxDecoration( color: const Color(0xFF423055), image: DecorationImage( fit: BoxFit.fill, image: AssetImage(getBaseImage('home_back')))), child: Scaffold( backgroundColor: Colors.transparent, body: SafeArea( child: GetBuilder(builder: (CircleLogic controller) { return Stack( children: [ Column(children: [ Obx(() { return navigatorItem(controller.statistics.value); }), // Text(controller.state.msg), //组件使用 ]), Container( margin: EdgeInsets.only(top: 45.sp), child: PageView( controller: _pageController, onPageChanged: (index) { _tabController.animateTo(index); print("index=" + index.toString()); }, children: [ circleList(controller), vicinityList(controller), ], ), ), logic.isShowCircle ? Positioned( bottom: 36.sp, right: 10.sp, child: GestureDetector( onTap: () async { List numbers = []; numbers.add(MyConfigData( logic.getCircleIndex().id.toString(), logic.getCircleIndex().title!, false)); var data = await Get.toNamed( AppRoutes.Call_out, arguments: {'numbers': numbers}); }, child: Image.asset( getCircleImage('send_msg'), width: 60.sp, ))) : Center() ], ); }), ), )); }); } Widget vicinityList(CircleLogic controller) { return SmartRefresher( controller: logic.refreshController, onRefresh: _onRefresh, onLoading: _onLoading, enablePullUp: logic.myVip>0, child: ListView.builder( padding: EdgeInsets.all(10.sp), itemCount: logic.myVip == 0 ? logic.vicinityList.length + 2 : logic.vicinityList.length + 1, itemBuilder: (context, index) { if (index == 0) { return bannerView(controller); } else { if (logic.myVip == 0 && index == logic.vicinityList.length+1) { return showVipView(); } else { return ListItem(logic.vicinityList[index-1], index-1); } } }, ), ); } Widget showVipView() { return Container( margin: EdgeInsets.only(top: 10.sp), color: const Color(0xB30B011B), padding: EdgeInsets.symmetric(vertical: 14.sp, horizontal: 20.sp), child: Column( children: [ Center( child: Text( "VIP特权", style: TextStyle(color: Colors.white, fontSize: 16.sp), ), ), Container( padding: EdgeInsets.only(top: 18.sp), child: Text( "开通VIP后,才能查看更多附近的圈友,也可以根据您的喜好、属性、角色、取向等筛选出想要认识的人,还可以获得其他十几种会员特权,拥有更多不一样的体验", style: TextStyle(color: Colors.white, fontSize: 12.sp), ), ), GestureDetector( onTap: () async { logic.showRechargeDialog(); }, child: Center( child: Container( margin: EdgeInsets.only(top: 14.sp), decoration: BoxDecoration( borderRadius: BorderRadius.circular(17), gradient: const LinearGradient( colors: [ Color(0xFF06F9FA), Color(0xFFDC5BFD), ], begin: Alignment.centerLeft, end: Alignment.centerRight, ), ), padding: EdgeInsets.symmetric( vertical: 10.sp, horizontal: 55.sp, ), child: const Text( "前往开通VIP", style: TextStyle( color: Colors.white, fontSize: 12, ), ), ), )) ], )); } Widget ListItem(VicinityItemBean item, int index) { return GestureDetector( onTap: (){ Get.toNamed(AppRoutes.UserInfoActivity, arguments: item.id.toString()); }, child: Container( margin: EdgeInsets.only(top: 10.sp), // padding: EdgeInsets.only( left: 8.sp, right: 8.sp), width: Get.width, height: 200.sp, decoration: BoxDecoration( image: DecorationImage( fit: BoxFit.fill, image: AssetImage( getCircleImage('pic_bg'), ))), child: Stack( children: [ Container( margin: EdgeInsets.only(top: 1.sp, left: 1.sp, right: 1.sp), child: ClipRRect( borderRadius: BorderRadius.only( topLeft: Radius.circular(10.sp), topRight: Radius.circular(10.sp), ), child: item.images.length==0? Image( image: AssetImage(getCircleImage("icon_list_null")), width: Get.width, fit: BoxFit.fill, height: 92.sp, ):Container(), ), ), Column(children: [ Container( margin: EdgeInsets.only(right: 2.sp), child: Row( children: [ Container( margin: EdgeInsets.only(top: 6.sp, left: 8.sp), width: 88.sp, height: 88.sp, decoration: BoxDecoration( borderRadius: BorderRadius.circular(8.0), gradient: const LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Color(0xFF71F3F2), Color(0xFFF558FF), ], stops: [0.0365, 0.9427], ), ), padding: EdgeInsets.all(2.sp), child: ClipRRect( borderRadius: BorderRadius.circular(8.0), child: Image.network(item.avatarThumb, width: 88.sp, height: 88.sp, fit: BoxFit.cover), ), ), Expanded( child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Container( margin: EdgeInsets.only(top: 6.sp), child: Row( children: [ for (int i = 0; i < item.images.length; i++) GestureDetector( onTap: (){ Get.toNamed(AppRoutes.Swiper, arguments: {'imaglist': item.images, 'index': i}); }, child: ListAlbumItem(item.images[i], i)), ], ), ), ), ), ], ), ), Container( margin: EdgeInsets.only(top: 6.sp, left: 9.sp), child: Row( children: [ Text( item.nickname, style: TextStyle( fontWeight: FontWeight.bold, color: const Color.fromRGBO(247, 250, 250, 1.0), fontSize: 16.sp, ), ), SizedBox(width: 8.sp), _buildInfoRow(item), const Spacer(), Container( margin: EdgeInsets.only(right: 8.sp), child:item.isOnline==1? Text( "当前在线", style: TextStyle( color: const Color.fromRGBO(247, 250, 250, 1.0), fontSize: 12.sp, ), ):Container(), ), ], ), ), Container( height: 50.sp, // 设置固定高度 width: Get.width, margin: EdgeInsets.symmetric( horizontal: 8.0), child: Align( alignment: Alignment.centerLeft, // 文本左对齐,垂直居中 child: Text( item.signature, maxLines: 2, style: TextStyle(color: Colors.white,fontSize: 14.sp), overflow: TextOverflow.ellipsis, ), ), ), Container( margin: EdgeInsets.only(left: 8.sp,right: 3.sp), child: _buildInterestsListView(item.interests)) ]), ], )), ); } Widget _buildInterestsListView(List interests) { return Align( alignment: Alignment.centerLeft, child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( children: [ for (int index = 0; index < interests.length; index++) GestureDetector( onTap: () { Get.toNamed(AppRoutes.Signal_circle_list, arguments: interests[index].id); }, child: Container( margin: EdgeInsets.only(right: 11.sp), decoration: BoxDecoration( borderRadius: BorderRadius.circular(17.0), gradient: const LinearGradient( colors: [ Color(0xFF06F9FA), Color(0xFFDC5BFD), ], ), color: const Color(0xFF392D53), ), child: Container( margin: EdgeInsets.all(0.2.sp), decoration: BoxDecoration( borderRadius: BorderRadius.circular(17.0), color: const Color(0xFF392D53), ), child: Padding( padding: EdgeInsets.only( top: 2.sp, bottom: 2.sp, left: 15.sp, right: 15.sp, ), child: Center( child: Text( interests[index].title, style: const TextStyle( fontSize: 13.0, color: Colors.white, ), ), ), ), ), ), ), ], ), ), ); } Widget _buildInfoRow(VicinityItemBean item) { String ageMsg = getAgeCOntent(item!.gender, item!.age, item!.role, item!.orientation); return Row( children: [ Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(17), gradient: const LinearGradient( colors: [ Color.fromRGBO(141, 255, 248, 1.0), Color.fromRGBO(181, 211, 255, 1.0), ], begin: Alignment.centerLeft, end: Alignment.centerRight, ), ), padding: EdgeInsets.only( top: 2.sp, bottom: 2.sp, left: 10.sp, right: 10.sp, ), child: Text( ageMsg, style: const TextStyle( color: Colors.black, fontSize: 10, ), ), ), const SizedBox(width: 6), if (item.vip > 0) Image( image: AssetImage(getBaseImage(item.vip == 1 ? "vip" : 'year_vip')), width: 44.sp, height: 18.sp, ), ], ); } Widget ListAlbumItem(String item, int index) { return Container( margin: EdgeInsets.symmetric(horizontal: 2.sp), child: CachedNetworkImage( width: 88.sp, height: 88.sp, fit: BoxFit.cover, imageUrl: item+"?imageView2/1/w/176/h/176/q/75",), ); } void _onRefresh() async { logic.vicinityPage = 1; logic.offset = 0; logic.getNearByList(); // logic.refreshController.refreshCompleted(); } void _onLoading() async { if(logic.myVip>0){ logic.vicinityPage = logic.vicinityPage + 1; // logic.getNearByList(); }else{ logic.refreshController.loadComplete(); } } Widget bannerView(CircleLogic controller) { return SizedBox( height: 160.sp, // margin: EdgeInsets.symmetric(horizontal: 16.sp), child: Swiper( autoplay: logic.bannerList.length > 1, controller: logic.swiperController, loop: logic.bannerList.length>1?true:false, // index:logic.index, itemBuilder: (BuildContext context, int index) { print(logic.bannerList[index].picUrl); return GestureDetector( onTap: () async { print(logic.bannerList[index].param); Get.toNamed(AppRoutes.WebViewActivity, arguments: { 'title': "", "url": logic.bannerList[index].param.toString() }); }, child: SizedBox( width: Get.width, child: ClipRRect( borderRadius: BorderRadius.circular(15.sp), child: CachedNetworkImage( imageUrl: logic.bannerList[index].picUrl, fit: BoxFit.fill, width: Get.width, ), )), ); }, itemCount: logic.bannerList.length, pagination: SwiperPagination( margin: EdgeInsets.all(5.0.sp), // 设置外边距 alignment: Alignment.bottomCenter, builder: DotSwiperPaginationBuilder( color: Colors.white, // 小圆点的颜色 activeColor: logic.bannerList.length == 1 ? Color(0x00FFFFFF) : Color(0xFFFF4D7C), // 当前索引小圆点的颜色 ), ), // control: new SwiperControl(), //左右的那个箭头,在某模拟器中会出现蓝线 ), ); } Widget circleList(CircleLogic controller) { return Swiper( itemBuilder: (BuildContext context, int index) { var bean = logic.circle.lists[index]; // final GlobalKey infoListViewKey = GlobalKey(); return InfoListView(index, bean, logic); }, onIndexChanged: (index) { controller.state.index = index; if (index == logic.circle.lists.length - 1) { logic.loadMore(); } print(index.toString()); }, index: controller.state.index, itemCount: logic.circle.lists.length, viewportFraction: 0.93, // scale: 0.9, loop: false, key: UniqueKey(), // pagination: new SwiperPagination(),//如果不填则不显示指示点 // control: new SwiperControl(),//如果不填则不显示左右按钮 ); } Widget navigatorItem(DataModel statistics) { List urlList = []; List infoList = []; if (statistics != null) { infoList = statistics.lastVisitUsers; if (infoList.isNotEmpty) { for (var element in infoList) { urlList.add(element["avatar"]); } } } List widgets = []; for (int i = 0; i < urlList.length; i++) { var element = urlList[i]; widgets.add(Positioned( left: 15.sp * i, child: circleWidget(element), )); } if (statistics != null && widgets.isNotEmpty) { widgets.add(Positioned( left: 15.sp * urlList.length, child: circleWidget(statistics.visitCount.toString()), )); } return Container( width: Get.width, padding: EdgeInsets.only(left: 18.sp, right: 18.sp), height: 44.sp, child: Stack( alignment: Alignment.center, children: [ logic.isShowCircle ? Positioned( left: 0, child: GestureDetector( onTap: () { Get.toNamed(AppRoutes.VisitorListActivity); }, child: SizedBox( width: 30.sp * widgets.length, height: 44.sp, child: Stack( alignment: Alignment.centerLeft, children: widgets, ), ), ), ) : GestureDetector( onTap: (){ showCityPiker(context); }, child: Row( children: [ Image.asset( getCircleImage('icon_city'), width: 24.sp, ), Container( margin: EdgeInsets.only(left: 4.sp, top: 4.sp), child: Text( logic.cityName, style: TextStyle(color: Colors.white, fontSize: 16.sp), )) ], ), ), Container( alignment: Alignment.center, //padding: EdgeInsets.symmetric(horizontal: 10.sp), height: 27.sp, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ TabBar( isScrollable: true, controller: _tabController, labelPadding: EdgeInsets.symmetric(horizontal: 13.0), indicator: UnderlineTabIndicator( borderSide: BorderSide( color: const Color(0xFF00FFF4), width: 2.sp, ), insets: EdgeInsets.symmetric(horizontal: 6.0.sp), borderRadius: BorderRadius.circular(18.0), ), indicatorColor: const Color(0xFF00FFF4), indicatorWeight: 2.sp, labelColor: const Color(0xFF00FFF4), unselectedLabelColor: const Color(0xB3FFFFFF), indicatorSize: TabBarIndicatorSize.label, tabs: [ Tab( child: Text( '发现', style: TextStyle( fontSize: 18.sp, ), ), ), Tab( child: Text( '附近', style: TextStyle( fontSize: 18.sp, ), ), ), ], labelStyle: TextStyle( color: const Color(0xFF00FFF4), fontSize: 18.sp, shadows: [ Shadow( color: const Color(0xFFF657FF).withOpacity(0.5), offset: Offset(0, -2), // 阴影偏移 blurRadius: 3, // 阴影模糊半径 // spreadRadius: 0 ), ], ), unselectedLabelStyle: TextStyle( // color: const Color(0xB3FFFFFF), fontSize: 18.sp, shadows: [ Shadow( // color: const Color(0xFFF657FF), offset: const Offset(0, -1), blurRadius: 3.0.sp, ), ], ), onTap: (index) { _pageController.animateToPage( index, // 目标页面索引 duration: const Duration(milliseconds: 300), // 动画时长 curve: Curves.ease, // 动画曲线 ); }, ), ], ), ), // ShaderMask( // shaderCallback: (Rect bounds) { // return const LinearGradient( // begin: Alignment(0.0, -1.0), // end: Alignment.bottomCenter, // colors: [Color(0xff71F3F2), Color(0xffF657FF)], // ).createShader(Offset.zero & bounds.size); // }, // child: GestureDetector( // onTap: (){ // // }, // child: Text( // '发现', // style: TextStyle( // fontSize: 18.sp, // fontWeight: FontWeight.w600, // color: Colors.white, // shadows: const [Shadow(color: Color(0xffF657FF), offset: Offset(0.0, -1))], // ), // ), // ), // ), Positioned( right: 0, child: logic.isShowCircle ? GestureDetector( onTap: () { Get.toNamed(AppRoutes.MyCircle, arguments: ''); }, child: Image.asset( getCircleImage('my_circle'), width: 64.sp, ), ) : GestureDetector( onTap: () { _showBottomSheet(context); }, child: Image.asset( getCircleImage('icon_screen'), width: 24.sp, ), ), ), ], ), ); } void _showBottomSheet(BuildContext context) { showModalBottomSheet( context: context, backgroundColor: Colors.transparent, builder: (BuildContext context) { return ScreenBottomSheetDialog( genderList: logic.genderList, orientationList: logic.orientationList, roleList: logic.roleList, callback: (genderList, orientationList, roleList) { logic.offset = 0; logic.getNearByList(); }, ); // Use your custom widget here }, ); } circleWidget(String url, {double width = 30}) { return GestureDetector( child: Stack( alignment: Alignment.center, children: [ Image.asset( getCircleImage('avatar_bg'), width: width.sp, ), url.contains("http") ? ClipOval( child: Image.network( url, width: (width - 1).sp, height: (width - 1).sp, fit: BoxFit.cover, ), ) : Text( url, style: TextStyle(color: Color(0xffF756FF), fontSize: 12.sp), ) ], )); } void _showTextContentDialog(BuildContext context, String msg) { showDialog( context: context, builder: (BuildContext context) { return Dialog( backgroundColor: Colors.transparent, child: Container( height: 300.sp, padding: EdgeInsets.all(1.0), child: Stack( children: [ Container( decoration: BoxDecoration( shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(10.0), gradient: LinearGradient( colors: [Color(0xFFDD3DF4), Color(0xFF30FFD9)], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), ), ), Container( margin: EdgeInsets.all(1.sp), decoration: BoxDecoration( shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(10.0), gradient: LinearGradient( colors: [Color(0xFF4C3E5F), Color(0xFF324140)], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), ), ), Container( margin: EdgeInsets.only(top: 24.sp), child: Column( children: [ Container( margin: EdgeInsets.only( top: 12.sp, left: 14.sp, right: 14.sp), alignment: Alignment.center, child: Text( msg, textAlign: TextAlign.center, style: TextStyle( color: Color(0xCCF7FAFA), fontSize: 16.sp), ), ), ], ), ) ], ), ), ); }, ); } void _showOutCircleDialog( BuildContext context, CircleLogic controller, Circle bean) { showDialog( context: context, builder: (BuildContext context) { return Dialog( backgroundColor: Colors.transparent, child: Container( height: 160.sp, padding: EdgeInsets.all(1.0), child: Stack( children: [ Container( decoration: BoxDecoration( shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(10.0), gradient: LinearGradient( colors: [Color(0xFFDD3DF4), Color(0xFF30FFD9)], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), ), ), Container( margin: EdgeInsets.all(1.sp), decoration: BoxDecoration( shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(10.0), gradient: LinearGradient( colors: [Color(0xFF4C3E5F), Color(0xFF324140)], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), ), ), Container( margin: EdgeInsets.only(top: 24.sp), child: Column( children: [ Center( child: Text( "提示", style: TextStyle(color: Colors.white, fontSize: 16.sp), ), ), Container( margin: EdgeInsets.only( top: 12.sp, left: 14.sp, right: 14.sp), alignment: Alignment.center, child: Text( "是否确认退出该圈子。", textAlign: TextAlign.center, style: TextStyle( color: Color(0xCCF7FAFA), fontSize: 16.sp), ), ), Row( mainAxisAlignment: MainAxisAlignment.center, // mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ GestureDetector( onTap: () { Navigator.pop(context); }, child: Container( margin: EdgeInsets.only(top: 30.sp), decoration: BoxDecoration( borderRadius: BorderRadius.circular(17), gradient: LinearGradient( colors: [ Color(0x26FFFFFF), Color(0x26FFFFFF), ], begin: Alignment.centerLeft, end: Alignment.centerRight, ), ), padding: EdgeInsets.only( top: 10.sp, bottom: 10.sp, left: 52.sp, right: 52.sp), child: Text( "否", style: TextStyle( color: Colors.white, fontSize: 12, ), ), ), ), SizedBox(width: 24.sp), GestureDetector( onTap: () { Navigator.pop(context); logic.outCircle(bean.id.toString(), bean.isJoin!); }, child: Container( margin: EdgeInsets.only(top: 24.sp), decoration: BoxDecoration( borderRadius: BorderRadius.circular(17), gradient: LinearGradient( colors: [ Color(0xFF06F9FA), Color(0xFFDC5BFD), ], begin: Alignment.centerLeft, end: Alignment.centerRight, ), ), padding: EdgeInsets.only( top: 10.sp, bottom: 10.sp, left: 52.sp, right: 52.sp), child: Text( "是", style: TextStyle( color: Colors.white, fontSize: 12, ), ), ), ) ], ) ], ), ) ], ), ), ); }, ); } showCityPiker(context) { Pickers.showMultiLinkPicker(context, pickerStyle: DefaultPickerStyle.dark(), data: logic.cityMap, columeNum: 2, onConfirm: (List res, List position){ print(res); // print(logic.cityMap[res[0]][res[1]][0]); // controller.state.city = controller.cityMap[res[0]][res[1]][0]; // logic.state.city = res[1]; logic.cityName = res[1]; logic.offset = 0; logic.getNearByList(); // logic.getSuccess(); // logic.update(); } // onConfirm:(String province, String city, String? town){ // controller.state.role = city; // controller.update(); // // } ); } }