123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- 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<StatefulWidget> createState() {
- return _GameInfoViewState();
- }
- }
- class _GameInfoViewState extends State<GameInfoView> with InjectApi, AutomaticKeepAliveClientMixin {
- // 私有属性忘了下划线...
- // bool _flag = true;
- List<GameInfoData> _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<List<GameInfoData>> checkIsLocal() async {
- List<GameInfoData> _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: <Widget>[
- // 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: <Widget>[
- // 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<List<GameInfoData>>(
- // future: checkIsLocal(),
- // builder: (_, snapshot) {
- // return snapshot.connectionState != ConnectionState.done
- // ? Container()
- // : snapshot.data.isEmpty
- // ? Container()
- // : Column(crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[
- // _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: <Widget>[
- Text(
- "${item.name}",
- style: Theme.of(context).textTheme.headline4.copyWith(fontSize: 20.0),
- ),
- const SizedBox(height: 5.0,),
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: <Widget>[
- 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: <Widget>[
- 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: <Widget>[
- 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()
- ],
- ),
- ),
- );
- }
- }
|