import 'dart:math'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_easyrefresh/easy_refresh.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; import 'package:get_it/get_it.dart'; import 'package:provider/provider.dart'; import 'package:sport/bean/post_user.dart'; import 'package:sport/bean/user.dart'; import 'package:sport/constant/ui.dart'; import 'package:sport/pages/my/achievement_detail_page.dart'; import 'package:sport/provider/user_model.dart'; import 'package:sport/router/navigator_util.dart'; import 'package:sport/services/api/login_api.dart'; import 'package:sport/widgets/dialog/popupmenu.dart' as menu; import 'package:sport/widgets/image.dart'; import 'package:sport/widgets/refresh_footer.dart'; import 'package:sport/widgets/refresh_header.dart' as header; import 'package:sport/widgets/space.dart'; Widget buildSocialUserWidget(BuildContext context, PostUser? user, int createTime, int avatarWidth) { return user == null ? Container() : GestureDetector( onTap: () => NavigatorUtil.goSocialUserDetail(context, user), child: Row( children: [ Padding( padding: const EdgeInsets.fromLTRB(12.0, 0, 8.0, 0), child: CircleAvatar(backgroundColor: Colors.black26,backgroundImage: userAvatarProvider(user.avatar), radius: avatarWidth / 2), ), Text( user.name ?? "", style: Theme.of(context).textTheme.subtitle1!.copyWith(fontWeight: FontWeight.w600), ), ], )); } Widget buildLabelWidget(BuildContext context, String title) { return Container( padding: EdgeInsets.fromLTRB(ui_padding, 10.0, ui_padding, 10.0), child: Text( title, style: Theme.of(context).textTheme.headline1!.copyWith( fontSize: 16.0, ), )); } Widget gameTag(BuildContext context, String name) { return Container( decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(50)), border: Border.all( color: Theme.of(context).accentColor, width: 1, ), ), padding: EdgeInsets.fromLTRB(8, 0, 8, 1), child: Text( name, style: Theme.of(context).textTheme.bodyText1!.copyWith(color: Theme.of(context).accentColor), strutStyle: fixedLine, ), ); } Widget achievementGroupWidget(List? achievements) { return achievements == null || achievements.isEmpty ? Center(child: Container(child: Padding(padding: const EdgeInsets.all(24.0), child: Text("还未获得成就")))) : AlignedGridView.count( padding: EdgeInsets.zero, shrinkWrap: true, physics: NeverScrollableScrollPhysics(), crossAxisCount: 4, itemCount: min(4, achievements.length), itemBuilder: (BuildContext context, int index) => achievementWidget(context, achievements[index]), crossAxisSpacing: 12.0, ); } Widget achievementWidget(BuildContext context, Achievement item, {double w = 70, bool replace = false, bool isRadius = false, bool jump = true, showCount = false}) => InkWell( onTap: () async { // 不能看别人的成就... if (item.userId != null && Provider.of(context, listen: false).user.id != item.userId) return; // if (jump == true) NavigatorUtil.goAchievementDetails(context, id: item.id, userId: item.userId ?? 0, replace: replace); if (jump == true) { List relateAchievements = (await GetIt.I().getAchieveDetailInfo(item.id ?? 0)).data?.relateAchievements ?? []; showSharePopup(context, relateAchievements, item.id ?? 0); } }, child: Stack( children: [ Center( child: Column( children: [ isRadius ? CircleAvatar(backgroundColor: Colors.black26,backgroundImage: CachedNetworkImageProvider(item.logo ?? ""), radius: w / 2) : item.createdAt == "" ? ColorFiltered( colorFilter: ColorFilter.mode(Color(0xffF1F1F1), BlendMode.color), child: CachedNetworkImage(width: w, height: w, imageUrl: item.logo ?? ""), ) : Container( width: w, height: w, child: CachedNetworkImage(imageUrl: item.logo ?? ""), ), Space( height: 5, ), Text(item.seriesName ?? item.name ?? "", // style: Theme.of(context).textTheme.subtitle1!.copyWith(fontSize: w < 80 ? 12 : 14), style: Theme.of(context).textTheme.subtitle1!.copyWith(fontSize: 12)) ], ), ), showCount ? Positioned( top: 0, right: 10.0, child: Container( alignment: Alignment.center, width: 32.0, height: 21.0, decoration: BoxDecoration( image: DecorationImage( image: AssetImage("lib/assets/img/bg_achievement_number.png"), fit: BoxFit.cover, )), child: Text( "${item.seriesCount}枚", style: TextStyle(fontSize: 12.0, color: Colors.white), strutStyle: StrutStyle(forceStrutHeight: true, height: 0.8), ), )) : Container() ], )); Widget sportBeEquivalentTo(BuildContext context, int consume, {bool highlight = false}) => Padding( padding: EdgeInsets.all(10.0), child: Text( "消耗了 ${(consume / 50).round()} 块小饼干", style: Theme.of(context).textTheme.subtitle1!, ), ); // Row( // mainAxisAlignment: MainAxisAlignment.spaceAround, // children: [ // Column( // children: [ // Image.asset("lib/assets/img/gamedetail_image_walk.png"), // Space( // height: 8, // ), // RichText( // text: TextSpan(children: [ // TextSpan(text: '步行', style: Theme.of(context).textTheme.bodyText1!), // TextSpan( // text: '${(consume / 3 * 90).floor()}', // style: highlight // ? Theme.of(context).textTheme.bodyText1!.copyWith(color: Theme.of(context).accentColor) // : Theme.of(context).textTheme.bodyText1!), // TextSpan(text: '步', style: Theme.of(context).textTheme.bodyText1!), // ]), // ) // ], // ), // Column( // children: [ // Image.asset("lib/assets/img/gamedetail_image_run.png"), // Space( // height: 8, // ), // RichText( // text: TextSpan(children: [ // TextSpan(text: '跑步', style: Theme.of(context).textTheme.bodyText1!), // TextSpan( // text: '${(consume / 60 / 1.036).toStringAsFixed(1)}', // style: highlight // ? Theme.of(context).textTheme.bodyText1!.copyWith(color: Theme.of(context).accentColor) // : Theme.of(context).textTheme.bodyText1!), // TextSpan(text: '公里', style: Theme.of(context).textTheme.bodyText1!), // ]), // ) // ], // ), // Column( // children: [ // Image.asset("lib/assets/img/gamedetail_image_riding.png"), // Space( // height: 8, // ), // RichText( // text: TextSpan(children: [ // TextSpan(text: '单车', style: Theme.of(context).textTheme.bodyText1!), // TextSpan( // text: '${(consume / 60 / 0.6142).toStringAsFixed(1)}', // style: highlight // ? Theme.of(context).textTheme.bodyText1!.copyWith(color: Theme.of(context).accentColor) // : Theme.of(context).textTheme.bodyText1!), // TextSpan(text: '公里', style: Theme.of(context).textTheme.bodyText1!), // ]), // ) // ], // ), // ], // ); const REFRESH_INFO_COLOR = Color(0xff999999); header.ClassicalHeader buildClassicalHeader({ double extent = 80.0, double triggerDistance = 90.0, Color infoColor = REFRESH_INFO_COLOR, Color textColor = REFRESH_INFO_COLOR, Color bgColor = Colors.transparent, }) { return header.ClassicalHeader( extent: extent, triggerDistance: triggerDistance, showInfo: false, refreshText: '下拉刷新', refreshFailedText: '刷新失败', refreshedText: '刷新完成', refreshingText: '正在刷新...', refreshReadyText: '释放刷新', infoColor: infoColor, bgColor: bgColor, textColor: infoColor, ); } Footer buildClassicalFooter() { return CustomClassicalFooter( showInfo: false, loadedText: '加载完成', loadReadyText: '释放加载', loadFailedText: '加载失败', loadText: '拉动加载', loadingText: '正在加载...', noMoreText: "没有更多了~", infoColor: Color(0xff999999)); } PopupMenuEntry menuDivider() => menu.PopupMenuItem( height: 1, child: Divider( height: 1, ), ); PopupMenuEntry menuItem(String value, String icon, String text) => menu.PopupMenuItem( value: value, child: Row( mainAxisSize: MainAxisSize.min, children: [ Image.asset( "lib/assets/img/$icon", width: 24, ), SizedBox( width: 4, ), Text( text, ) ], ), ); PopupMenuEntry menuItemCenter(dynamic value, String text) => menu.PopupMenuItem( value: value, child: Center( child: Text( text, )), ); PopupMenuEntry menuItemSelected(dynamic value, String text, bool select) => menu.PopupMenuItem( value: value, child: Row( mainAxisSize: MainAxisSize.min, children: [ Container( alignment: AlignmentDirectional.centerStart, constraints: BoxConstraints(minWidth: 60), padding: const EdgeInsets.symmetric(horizontal: 8.0), child: select ? Text( text, style: TextStyle(color: Color(0xffFFC400)), ) : Text( text, ), ), if (select) Image.asset( "lib/assets/img/pop_icon_selected.png", width: 24, ), ], )); List divideMenus(Iterable tiles) { assert(tiles != null); final Iterator iterator = tiles.iterator; final PopupMenuEntry divider = menuDivider(); final List list = []; while (iterator.moveNext()) { list.add(iterator.current); list.add(divider); } if (list.length > 1) list.removeAt(list.length - 1); return list; } const StrutStyle fixedLine = StrutStyle(height: 1.1, forceStrutHeight: true);