import 'dart:io'; import 'dart:ui'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:device_apps/device_apps.dart'; import 'package:flutter/material.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart'; import 'package:sport/bean/game.dart'; import 'package:sport/constant/ui.dart'; import 'package:sport/constant/ui.dart' show ui_padding, ui_margin_list; import 'package:sport/router/navigator_util.dart'; import 'package:sport/router/routes.dart'; import 'package:sport/services/api/inject_api.dart'; import 'package:sport/widgets/button_primary.dart'; import 'package:sport/widgets/decoration.dart'; import 'package:sport/widgets/dialog/share_popup.dart'; import 'package:sport/widgets/game_run.dart'; import 'package:sport/widgets/image.dart'; import 'package:sport/widgets/loading.dart'; import 'package:sport/widgets/misc.dart'; import 'package:sport/widgets/space.dart'; class GameInfoView extends StatefulWidget { @override State createState() { return _GameInfoViewState(); } } class _GameInfoViewState extends State with InjectApi, AutomaticKeepAliveClientMixin { // 私有属性忘了下划线... // bool _flag = true; List _data; void initState() { initData(); super.initState(); } initData() async { final data = await api.getGameAll(); // 为什么我还是选择了用setState vmodel那种是在理解不了??? _data = data.results; setState(() {}); } @override void dispose() { super.dispose(); } Future> checkIsLocal() async { List _myGames = []; for (GameInfoData data in _data) { if (Platform.isAndroid) { data.isLocal = await DeviceApps.isAppInstalled(data.packageNameAndroid); if (data.isLocal == true) { _myGames.add(data); } } } return _myGames; // setState(() {}); } Widget _buildLabelWidget(String title) { return buildLabelWidget(context, title); } @override Widget build(BuildContext context) { super.build(context); return Scaffold( backgroundColor: Colors.white, body: _data != null ? CustomScrollView( slivers: [ // SliverToBoxAdapter( // child: InkWell( // onTap: () async { // }, // child: AspectRatio( // aspectRatio: 375 / 190.0, // child: Container( // decoration: BoxDecoration( // image: DecorationImage( // image: AssetImage("lib/assets/img/sport_banner.png"), // fit: BoxFit.cover, // //设置四周边框 // ), // ), // ), // )), // ), // // SliverToBoxAdapter( // // child: SharePopupDialog(), // // ), // SliverToBoxAdapter( // child: Column( // crossAxisAlignment: CrossAxisAlignment.start, // children: [ // SizedBox( // height: 15, // ), // _buildLabelWidget("运动项目"), // ], // ), // ), SliverToBoxAdapter( child: Container(margin: const EdgeInsets.fromLTRB(ui_padding, ui_padding, ui_padding, 6.0), decoration: card(), child: GameRun())), SliverList( delegate: SliverChildBuilderDelegate((content, index) { var item = _data[index]; return SportItem(item); }, childCount: _data.length), ), // SliverToBoxAdapter( // child: FutureBuilder>( // future: checkIsLocal(), // builder: (_, snapshot) { // return snapshot.connectionState != ConnectionState.done // ? Container() // : snapshot.data.isEmpty // ? Container() // : Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ // _buildLabelWidget("我的运动"), // Column( // children: snapshot.data // .map((item) => GameItem( // type: 1, // imgUrl: item.cover, // name: item.name, // time: item.sum.lastPlayAt, // id: item.id, // duration: item.sum.durationTotal, // data: item, // )) // .toList()), // ]); // }, // ), // ), SliverToBoxAdapter( child: SizedBox( height: 50, ), ) ], ) : RequestLoadingWidget()); } @override bool get wantKeepAlive => true; } // 中间的那个游戏列表 class SportItem extends StatelessWidget { final GameInfoData item; SportItem(this.item); @override Widget build(BuildContext context) { return InkWell( child: AspectRatio( aspectRatio: 351 / 120.0, child: Container( margin: const EdgeInsets.fromLTRB(ui_padding, 6.0, ui_padding, 6.0), // 约束宽高的 decoration: BoxDecoration( image: DecorationImage( image: CachedNetworkImageProvider(item.coverHorizontal), // NetWorkImage 返回的是Image fit: BoxFit.cover, //设置四周边框 ), borderRadius: const BorderRadius.all(Radius.circular(10.0)), ), child: Align( alignment: Alignment.bottomCenter, child: Container( width: double.infinity, // margin: EdgeInsets.symmetric(vertical: 8.0, horizontal: 12.0), // alignment: Alignment.bottomCenter, decoration: const BoxDecoration( gradient: const LinearGradient(begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ const Color(0x00000000), // Color(0x00000000), const Color(0xAA000000) ]), borderRadius: const BorderRadius.vertical(bottom: Radius.circular(10.0)), ), child: Container( padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 12.0), child: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "${item.name}", style: Theme.of(context).textTheme.headline4.copyWith(fontSize: 20.0), ), const SizedBox(height: 5.0,), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text("难度:", style: Theme.of(context).textTheme.bodyText1.copyWith(color: Colors.white)), Expanded( child: RatingBarIndicator( rating: item.difficulty / 20.0, itemBuilder: (context, index) => Image.asset("lib/assets/img/con_icon_difficulty_normal.png", color: const Color(0xffFFC400),), itemCount: 5, itemSize: 14.0, unratedColor: const Color(0xffCECECE), direction: Axis.horizontal, ), ), Text("${item.userCount}人在练", style: Theme.of(context).textTheme.bodyText1.copyWith(color: Colors.white)) ], ) ], ), ), ), ), ), ), onTap: () { NavigatorUtil.goGameDetails(context, details: item).then((value) { }); }, ); } } // 最下面的那个 // @type = 1 继续按钮 // @type = 2 右箭头 → // class GameItem extends StatelessWidget { int type; String name; String desc; String imgUrl; String time; int id; int duration; GameInfoData data; bool bold; GameItem({@required this.type, this.name, this.imgUrl, this.time, this.id, this.duration, this.desc, this.data, this.bold = false}); @override Widget build(BuildContext context) { return Container( margin: EdgeInsets.fromLTRB(ui_padding, 6.0, ui_padding, 6.0), padding: EdgeInsets.all(ui_padding), decoration: card(), child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { print(type); if (type == 2) { print(id); NavigatorUtil.goRankDetails(context, id, 1); } else { NavigatorUtil.goGameDetails(context, details: this.data); } }, child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ Container( width: 70.0, height: 70.0, margin: EdgeInsets.only(right: 12.0), child: ClipRRect( child: CachedNetworkImage( imageUrl: imgUrl, fit: BoxFit.cover, ), // 也可控件一边圆角大小 borderRadius: new BorderRadius.all(Radius.circular(6.0)), ), ), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "$name", style: bold ? Theme.of(context).textTheme.subtitle1.copyWith(fontSize: 16.0, fontWeight: FontWeight.w600) : Theme.of(context).textTheme.subtitle1.copyWith(fontSize: 16.0), ), SizedBox( height: 3, ), type == 1 ? Text( "总时长:${duration ~/ 60 != 0 ? "${duration ~/ 60}时" : ""}${duration % 60}分钟", style: Theme.of(context).textTheme.bodyText1, ) : Text("$desc", style: Theme.of(context).textTheme.bodyText1, maxLines: 1), SizedBox( height: 6, ), type == 1 ? Text( "最近打开: ${time ?? '未进行运动'}", style: Theme.of(context).textTheme.bodyText1, maxLines: 1, ) : Text( "${time}", style: Theme.of(context).textTheme.bodyText1, maxLines: 1, ), ], ), ), type == 1 ? PrimaryButton( width: 72, height: 35, content: "继续", callback: () { NavigatorUtil.goGameDetails(context, details: this.data); }, ) : arrowRight7() ], ), ), ); } }