run_target_custom_page.dart 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
  3. import 'package:sport/services/app_lifecycle_state.dart';
  4. import 'package:sport/widgets/appbar.dart';
  5. import 'package:sport/widgets/button_primary.dart';
  6. import 'package:sport/widgets/misc.dart';
  7. final Map<int, String> targetTypeMap = {0:"距离", 1:"时间", 2:"次数", 3:"步数"};
  8. final Map<int, String> targetTypeMapUnit = {0:"公里", 1:"分钟", 2:"次", 3:"步"};
  9. class RunTargetCustomPage extends StatefulWidget {
  10. final double target;
  11. final int type;
  12. const RunTargetCustomPage({Key? key, this.target = 0, required this.type}) : super(key: key);
  13. @override
  14. State<StatefulWidget> createState() => _PageState();
  15. }
  16. class _PageState extends LifecycleState<RunTargetCustomPage> {
  17. ValueNotifier<String> _valueTotal = ValueNotifier("");
  18. @override
  19. void initState() {
  20. super.initState();
  21. _valueTotal.value = widget.type == 0 ? "${widget.target.toStringAsFixed(2)}" : "${widget.target.toInt()}";
  22. }
  23. @override
  24. void dispose() {
  25. super.dispose();
  26. }
  27. late String _t = "";
  28. _text(int index) {
  29. var tt = _valueTotal.value;
  30. print("! index $index, $_t");
  31. int dot = _t.indexOf(".");
  32. if (dot > -1) {
  33. print("! index $index, $_t ${_t.substring(dot).length}");
  34. if (_t.substring(dot).length > 2 && index != 11) {
  35. return;
  36. }
  37. if (index == 9) return;
  38. }
  39. if (index < 9) {
  40. _t += (index + 1).toString();
  41. } else if (index == 9) {
  42. _t += ".";
  43. } else if (index == 10) {
  44. _t += "0";
  45. } else if (index == 11) {
  46. if (_t.length > 0) {
  47. _t = _t.substring(0, _t.length - 1);
  48. }
  49. if (_t.isEmpty) {
  50. _valueTotal.value = "";
  51. return;
  52. }
  53. }
  54. var check = true;
  55. try {
  56. var result = double.parse(_t);
  57. if (widget.type == 0) {
  58. if (result > 100) {
  59. check = false;
  60. }
  61. } else if (widget.type == 1) {
  62. if (result > 1440) {
  63. check = false;
  64. }
  65. }
  66. print("! result $result $_t");
  67. } catch (e) {
  68. print("! result $tt $_t $e");
  69. }
  70. if (check) {
  71. _valueTotal.value = "$_t";
  72. } else {
  73. _valueTotal.value = "$tt";
  74. _t = tt;
  75. }
  76. }
  77. @override
  78. Widget build(BuildContext context) {
  79. final double _height = (MediaQuery.of(context).size.height - 50) / 2 / 5;
  80. return Scaffold(
  81. backgroundColor: Colors.white,
  82. appBar: buildAppBar(context, title: "自定义${targetTypeMap[widget.type]}"),
  83. body: Column(
  84. children: [
  85. Expanded(
  86. child: Center(
  87. child: Column(
  88. mainAxisSize: MainAxisSize.min,
  89. children: [
  90. ValueListenableBuilder(
  91. valueListenable: _valueTotal,
  92. builder: (_, v, __) => Text(
  93. "$v",
  94. style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 80.0, fontFamily: "DIN"),
  95. )),
  96. SizedBox(
  97. height: 12.0,
  98. ),
  99. Text(
  100. "${targetTypeMapUnit[widget.type]}",
  101. style: Theme.of(context).textTheme.bodyText2!.copyWith(fontSize: 18.0),
  102. ),
  103. SizedBox(
  104. height: 30.0,
  105. ),
  106. PrimaryButton(
  107. callback: () {
  108. Navigator.pop(context, _valueTotal.value);
  109. },
  110. content: "确定",
  111. width: 90,
  112. height: 35,
  113. )
  114. ],
  115. ),
  116. ),
  117. ),
  118. Container(
  119. color: Color(0xfff1f1f1),
  120. padding: EdgeInsets.all(4),
  121. child: AlignedGridView.count(
  122. padding: EdgeInsets.zero,
  123. shrinkWrap: true,
  124. physics: NeverScrollableScrollPhysics(),
  125. crossAxisCount: 3,
  126. itemCount: 12,
  127. itemBuilder: (BuildContext context, int index) {
  128. if (index == 9) {
  129. if (widget.type == 0) {
  130. return Material(
  131. child: Ink(
  132. child: InkWell(
  133. onTap: () {
  134. _text(index);
  135. },
  136. child: Container(
  137. height: _height,
  138. child: Center(
  139. child: Text(
  140. ".",
  141. style: TextStyle(fontSize: 40, color: Color(0xff333333)),
  142. strutStyle: fixedLine,
  143. ),
  144. )),
  145. ),
  146. ),
  147. );
  148. } else {
  149. return Container();
  150. }
  151. } else if (index == 11) {
  152. return Material(
  153. child: Ink(
  154. child: InkWell(
  155. onTap: () {
  156. _text(index);
  157. },
  158. child: Container(
  159. height: _height,
  160. child: Center(child: Icon(Icons.backspace_outlined)),
  161. )),
  162. ),
  163. );
  164. }
  165. return Material(
  166. child: Ink(
  167. child: InkWell(
  168. onTap: () {
  169. _text(index);
  170. },
  171. child: Container(
  172. height: _height,
  173. child: Center(
  174. child: Text(
  175. index < 10 ? "${index + 1}" : "0",
  176. style: TextStyle(fontSize: 16.0, color: Color(0xff333333)),
  177. ))),
  178. ),
  179. ),
  180. );
  181. },
  182. mainAxisSpacing: 4.0,
  183. crossAxisSpacing: 4.0,
  184. ),
  185. )
  186. ],
  187. ),
  188. );
  189. }
  190. }