import 'dart:math'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:sport/bean/sport_target.dart'; import 'package:sport/pages/social/notification.dart'; import 'package:sport/services/api/inject_api.dart'; import 'package:sport/widgets/box.dart'; import 'package:sport/widgets/loading.dart'; import 'package:sport/widgets/misc.dart'; import 'package:sport/widgets/space.dart'; class TargetModify extends StatefulWidget { final SportTarget target; final bool editCustom; final bool padding; TargetModify({this.target, this.editCustom = true, this.padding = true}); @override createState() => _PageState(); } class _PageState extends State with InjectApi { Space space = Space(height: 5); List _tags = []; ValueNotifier _valueNotifierChoice = ValueNotifier(""); double _customDuration = 150; TextEditingController _textEditingController; final String _customName = '自定义'; @override void initState() { super.initState(); _textEditingController = TextEditingController(); api.getSportTargetAll().then((value) { _tags.addAll(value.results); if (_tags.isNotEmpty) { if (_tags.any((element) => element.name == _customName)) { var target = _tags.singleWhere((element) => element.name == _customName); _textEditingController.text = '${target.duration}'; _customDuration = target.duration.toDouble(); _valueNotifierChoice.value = target.name; TargetNotification(target: target).dispatch(context); } else { _tags.add(SportTarget(duration: 150, consume: kal(150), name: '自定义', intension: '自定义', id: -1)); _textEditingController.text = '150'; _valueNotifierChoice.value = _tags[0].name; TargetNotification(target: _tags[0]).dispatch(context); } } setState(() {}); }); } @override void dispose() { _textEditingController?.dispose(); _valueNotifierChoice?.dispose(); super.dispose(); } int kal(double duration) { var realTime = duration / 60; var realWeight = 60 * 2 / 190; return ((realTime * realWeight) * 671.1).round(); } @override Widget build(BuildContext context) { Widget body = Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ ValueListenableBuilder( valueListenable: _valueNotifierChoice, builder: (_, _value, __) => Container( child: Center( child: Wrap( spacing: 6, children: _tags.map((e) { String name = e.name; bool _selected = name == _value; return FractionallySizedBox( widthFactor: .31, child: ChoiceChip( padding: EdgeInsets.zero, pressElevation: 0, selected: _selected, label: Center( child: Text( "$name", strutStyle: fixedLine, )), labelStyle: _selected ? TextStyle(color: Colors.white, fontSize: 13.0) : TextStyle(color: Color(0xff333333), fontSize: 13.0), //未选定的时候背景 selectedColor: Theme.of(context).accentColor, //被禁用得时候背景 backgroundColor: Colors.white, disabledColor: Colors.white, shape: StadiumBorder( side: BorderSide(color: _selected ? Theme.of(context).accentColor : Color(0xffcecece), width: 0.5), ), onSelected: (name == (widget.target == null ? "" : widget.target.name) && name != _customName) ? null : (value) { _valueNotifierChoice.value = name; TargetNotification(target: e).dispatch(context); }, )); }).toList()), ), ), ), ValueListenableBuilder( valueListenable: _valueNotifierChoice, builder: (_, _value, __) => _tags.isEmpty ? RequestLoadingWidget() : _tags .where((element) => element.name == _value) .map((e) => Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( height: 15, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "目标强度:", style: Theme.of(context).textTheme.subtitle1, ), Text(e.intension, style: Theme.of(context).textTheme.subtitle1.copyWith(color: Theme.of(context).accentColor)) ], ), space, Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "每日目标时长:", style: Theme.of(context).textTheme.subtitle1, ), e.name != _customName ? Text("${e.duration}分钟", style: Theme.of(context).textTheme.subtitle1.copyWith(color: Theme.of(context).accentColor)) : !widget.editCustom ? Text("${e.duration}分钟", style: Theme.of(context).textTheme.subtitle1.copyWith(color: Theme.of(context).accentColor)) : Container( width: 70, height: 35, child: Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ Expanded( child: TextField( controller: _textEditingController, textAlign: TextAlign.right, maxLength: 3, maxLines: 1, style: Theme.of(context).textTheme.subtitle1.copyWith(color: Theme.of(context).accentColor), keyboardType: TextInputType.number, onTap: () { _textEditingController.clear(); ScrollToBottomNotification().dispatch(context); }, onChanged: (v) { if (v.length > 3) return; int inputValue = int.parse(v); int value = min(999, inputValue); // _textEditingController.text = "$value"; e.duration = value; e.consume = kal(e.duration.toDouble()); TargetNotification(target: e).dispatch(context); _customDuration = e.duration.toDouble(); setState(() {}); }, decoration: InputDecoration( counterText: '', contentPadding: EdgeInsets.zero, floatingLabelBehavior: FloatingLabelBehavior.never, border: UnderlineInputBorder( borderSide: BorderSide(color: Theme.of(context).accentColor), ), enabledBorder: UnderlineInputBorder( borderSide: BorderSide(color: Theme.of(context).accentColor), ), focusedBorder: UnderlineInputBorder( borderSide: BorderSide(color: Theme.of(context).accentColor), ))), ), Padding( padding: const EdgeInsets.only(bottom: 2.0), child: Text("分钟", style: Theme.of(context).textTheme.subtitle1), ), ], ), ) ], ), if (e.name == _customName) Stack( children: [ Padding( padding: const EdgeInsets.fromLTRB(18.0, 30.0, 14.0, 0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( " 0 ", style: TextStyle(fontSize: 12), ), Text( " 100", style: TextStyle(fontSize: 12), ), Text( " 200", style: TextStyle(fontSize: 12), ), Text( "300", style: TextStyle(fontSize: 12), ), ], ), ), Slider( activeColor: Theme.of(context).accentColor, inactiveColor: Color(0xfff1f1f1), min: 0, max: 300, onChanged: (double value) { setState(() { e.duration = value.toInt(); e.consume = kal(value); TargetNotification(target: e).dispatch(context); _customDuration = value; _textEditingController.text = '${e.duration}'; }); }, value: min(_customDuration, 300), ) ], ), space, Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "每日预计消耗:", style: Theme.of(context).textTheme.subtitle1, ), Text("${e.consume}kal", style: Theme.of(context).textTheme.subtitle1.copyWith(color: Theme.of(context).accentColor)) ], ), space, if (e.fitPeople?.isNotEmpty == true) Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "适用人群:", style: Theme.of(context).textTheme.subtitle1, ), Text(e.fitPeople, style: Theme.of(context).textTheme.subtitle1.copyWith(color: Theme.of(context).accentColor)) ], ), space, space, Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Divider( endIndent: 24.0, ), ), Text( "相当于", style: Theme.of(context).textTheme.bodyText1, ), Expanded( child: Divider( indent: 24.0, ), ) ], ), Padding( padding: const EdgeInsets.fromLTRB(0, 10, 0, 5), child: Center(child: sportBeEquivalentTo(context, e.consume, highlight: true)), ), space, Center( child: Text( "提示:请依据个人情况选择最适合自己的运动强度", style: Theme.of(context).textTheme.subtitle2.copyWith(color: Color(0xffFF5B1D)), ), ) ], )) .single), ], ); return widget.padding ? BoxWidget( body: body, ) : body; } } class TargetNotification extends Notification { TargetNotification({ @required this.target, }); final SportTarget target; }