import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:sport/pages/run/run_target_custom_page.dart'; import 'package:sport/pages/run/setting_page.dart'; import 'package:sport/router/navigator_util.dart'; import 'package:sport/services/app_lifecycle_state.dart'; import 'package:sport/widgets/appbar.dart'; import 'package:sport/widgets/button_primary.dart'; import 'package:sport/widgets/dialog/alert_dialog.dart'; import 'package:sport/widgets/dialog/request_dialog.dart'; import 'package:sport/widgets/misc.dart'; class RunTargetPage extends StatefulWidget { final double runTargetKm; final double runTargetDuration; RunTargetPage(this.runTargetKm, this.runTargetDuration); @override State createState() => _PageState(); } class _PageState extends LifecycleState with SingleTickerProviderStateMixin { late TabController _controller; @override void initState() { super.initState(); _controller = new TabController(length: 2, vsync: this, initialIndex: widget.runTargetDuration > 0 ? 1 : 0) ..addListener(() { setState(() {}); }); } @override void dispose() { super.dispose(); _controller.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: buildAppBar(context, title: "设定目标"), body: Padding( padding: const EdgeInsets.all(12.0), child: Column( children: [ Center( child: TabBar( controller: _controller, isScrollable: true, indicatorPadding: EdgeInsets.symmetric(horizontal: 10.0), indicatorWeight: 3, unselectedLabelColor: Color(0xff999999), labelStyle: TextStyle(fontSize: 16.0), unselectedLabelStyle: TextStyle(fontSize: 16.0), labelPadding: EdgeInsets.symmetric(vertical: 0.0, horizontal: 30.0), // indicator: const BoxDecoration(), // labelPadding: EdgeInsets.all(20.0), tabs: [ Tab( icon: Image.asset("lib/assets/img/setgoals_icon_kilometre_${_controller.index == 0 ? "press" : "normal"}.png"), text: "公里数", iconMargin: EdgeInsets.only(bottom: 3.0), ), Tab( icon: Image.asset("lib/assets/img/setgoals_icon_duration_${_controller.index == 1 ? "press" : "normal"}.png"), text: "运动时长", iconMargin: EdgeInsets.only(bottom: 3.0), ) ], ), ), Divider(), Expanded( child: Container( padding: const EdgeInsets.only(top: 30.0), child: TabBarView( controller: _controller, physics: NeverScrollableScrollPhysics(), children: [ _Form( type: 0, unit: "公里", items: [0.4, 0.8, 1, 3, 5, 10, 21.09, 42.19], labels: ["400米","800米", "1公里", "3公里", "5公里", "10公里", "半马", "全马"], target: widget.runTargetKm), _Form( type: 1, unit: "分钟", items: [10, 20, 30, 40, 60, 90], labels: ["10分钟", "20分钟", "30分钟", "40分钟", "60分钟", "90分钟"], target: widget.runTargetDuration, ), ], ), ), ) ], ), ), ); } } class _Form extends StatefulWidget { final double target; final int type; final String unit; final List items; final List labels; const _Form({Key? key,required this.type,required this.target, required this.unit,required this.items,required this.labels}) : super(key: key); @override State createState() => _FormState(); } class _FormState extends State<_Form> with RunSetting { ValueNotifier _valueTotal = ValueNotifier(0); ValueNotifier _valueIndex = ValueNotifier(0); @override void initState() { super.initState(); loadSetting().then((value) { if (widget.type == 0) { double target = widget.target > 0 ? widget.target : runTargetKm; _valueTotal.value = target > 0 ? target / 1000 : widget.items[0]; } else { double target = widget.target > 0 ? widget.target : runTargetDuration; _valueTotal.value = target > 0 ? target / 60 : widget.items[0]; } _valueIndex.value = widget.items.indexOf(_valueTotal.value); }); } @override bool autoLoadSetting() => false; @override void dispose() { super.dispose(); _valueIndex.dispose(); } @override Widget build(BuildContext context) { return SingleChildScrollView( child: Column( children: [ Row( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.baseline, textBaseline: TextBaseline.alphabetic, children: [ ValueListenableBuilder( valueListenable: _valueTotal, builder: (_, value, ___) => Text( widget.type == 0 ? "${value.toStringAsFixed(2)}" : "${value.toInt()}", style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 40.0, fontFamily: "DIN"), ), ), Padding( padding: const EdgeInsets.all(6.0), child: Text( widget.unit, style: Theme.of(context).textTheme.subtitle2, ), ), ], ), GestureDetector( onTap: () async { var result = await NavigatorUtil.goPage( context, (context) => RunTargetCustomPage( target: _valueTotal.value, type: widget.type, )); if (result != null) { var val = result.trim(); if (val.isEmpty == true) return; _valueTotal.value = double.parse(val); _valueIndex.value = -1; } }, child: Container( width: 80.0, height: 30.0, margin: const EdgeInsets.all(8.0), decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), border: Border.all( color: Theme.of(context).accentColor, width: .5, ), ), child: Center( child: Text( "自定义", style: Theme.of(context).textTheme.subtitle1!.copyWith(color: Theme.of(context).accentColor), strutStyle: fixedLine, )), ), ), const SizedBox( height: 15.0, ), Padding( padding: const EdgeInsets.symmetric(vertical: 20.0), child: ValueListenableBuilder( valueListenable: _valueIndex, builder: (_, value, __) => AlignedGridView.count( padding: EdgeInsets.zero, shrinkWrap: true, physics: NeverScrollableScrollPhysics(), crossAxisCount: 3, itemCount: widget.items.length, itemBuilder: (BuildContext context, int index) => GestureDetector( onTap: () { _valueIndex.value = index; _valueTotal.value = widget.items[index]; }, child: Center( child: Container( height: 66.0, decoration: BoxDecoration( image: value == index ? DecorationImage(image: AssetImage("lib/assets/img/control_img_selected.png"), alignment: Alignment.bottomRight) : null, borderRadius: BorderRadius.circular(10), border: Border.all( color: value == index ? Theme.of(context).accentColor : const Color(0xffCECECE), width: .5, ), ), child: Center( child: Text("${widget.labels[index]}", style: value == index ? Theme.of(context).textTheme.subtitle1!.copyWith(fontSize: 16.0, color: Theme.of(context).accentColor) : Theme.of(context).textTheme.subtitle1!.copyWith(fontSize: 16.0))), )), ), crossAxisSpacing: 12.0, mainAxisSpacing: 12.0, ), ), ), const SizedBox(height: 12,), PrimaryButton( height: 44.0, content: "确定目标", callback: () async { double runTargetDuration = 0; double runTargetKm = 0; if (widget.type == 0) { this.runTargetKm = runTargetKm = _valueTotal.value * 1000; // runTargetDuration = 0; } else { // runTargetKm = 0; this.runTargetDuration = runTargetDuration = _valueTotal.value * 60; } updateSetting(); Navigator.pop(context, [runTargetKm, runTargetDuration]); }, ) ], ), ); } }