timer_settings_page.dart 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_clock/model/timer_settings.dart';
  3. /// Description: 倒计时设置页面
  4. /// Time : 04/22/2025 Tuesday
  5. /// Author : liuyuqi.gov@msn.cn
  6. class TimerSettingsPage extends StatefulWidget {
  7. final TimerSettings settings;
  8. const TimerSettingsPage({Key? key, required this.settings}) : super(key: key);
  9. @override
  10. _TimerSettingsPageState createState() => _TimerSettingsPageState();
  11. }
  12. class _TimerSettingsPageState extends State<TimerSettingsPage> {
  13. late String _sound;
  14. late double _volume;
  15. late bool _vibrate;
  16. late bool _loop;
  17. late bool _alignToHour;
  18. final List<String> _availableSounds = ['Dripping', 'Alarm', 'Bell'];
  19. @override
  20. void initState() {
  21. super.initState();
  22. _sound = widget.settings.sound;
  23. _volume = widget.settings.volume;
  24. _vibrate = widget.settings.vibrate;
  25. _loop = widget.settings.loop;
  26. _alignToHour = widget.settings.alignToHour;
  27. }
  28. // Save settings
  29. Future<TimerSettings> _saveSettings() async {
  30. final updatedSettings = TimerSettings(
  31. sound: _sound,
  32. volume: _volume,
  33. vibrate: _vibrate,
  34. loop: _loop,
  35. alignToHour: _alignToHour,
  36. );
  37. await updatedSettings.saveSettings();
  38. return updatedSettings;
  39. }
  40. @override
  41. Widget build(BuildContext context) {
  42. return WillPopScope(
  43. onWillPop: () async {
  44. final updatedSettings = await _saveSettings();
  45. Navigator.pop(context, updatedSettings);
  46. return false;
  47. },
  48. child: Scaffold(
  49. backgroundColor: Colors.white,
  50. appBar: AppBar(
  51. backgroundColor: Colors.white,
  52. elevation: 0,
  53. leading: IconButton(
  54. icon: Icon(Icons.close, color: Colors.black),
  55. onPressed: () async {
  56. final updatedSettings = await _saveSettings();
  57. Navigator.pop(context, updatedSettings);
  58. },
  59. ),
  60. title: Text(
  61. 'Settings',
  62. style: TextStyle(color: Colors.black, fontSize: 24),
  63. ),
  64. centerTitle: true,
  65. ),
  66. body: ListView(
  67. children: [
  68. _buildSoundSetting(),
  69. _buildVolumeSetting(),
  70. _buildVibrateSetting(),
  71. _buildLoopSetting(),
  72. _buildAlignToHourSetting(),
  73. ],
  74. ),
  75. ),
  76. );
  77. }
  78. Widget _buildSoundSetting() {
  79. return Column(
  80. crossAxisAlignment: CrossAxisAlignment.start,
  81. children: [
  82. Padding(
  83. padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
  84. child: Row(
  85. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  86. children: [
  87. Text(
  88. 'Sound',
  89. style: TextStyle(fontSize: 18),
  90. ),
  91. GestureDetector(
  92. onTap: () {
  93. _showSoundPicker();
  94. },
  95. child: Row(
  96. children: [
  97. Text(
  98. _sound,
  99. style: TextStyle(fontSize: 16, color: Colors.grey[700]),
  100. ),
  101. Icon(
  102. Icons.chevron_right,
  103. color: Colors.grey[700],
  104. ),
  105. ],
  106. ),
  107. ),
  108. ],
  109. ),
  110. ),
  111. Divider(),
  112. ],
  113. );
  114. }
  115. Widget _buildVolumeSetting() {
  116. return Column(
  117. crossAxisAlignment: CrossAxisAlignment.start,
  118. children: [
  119. Padding(
  120. padding: const EdgeInsets.fromLTRB(16, 8, 16, 8),
  121. child: Text(
  122. 'Vol.',
  123. style: TextStyle(fontSize: 18),
  124. ),
  125. ),
  126. Slider(
  127. value: _volume,
  128. min: 0.0,
  129. max: 1.0,
  130. activeColor: Colors.orange,
  131. inactiveColor: Colors.grey[300],
  132. onChanged: (value) {
  133. setState(() {
  134. _volume = value;
  135. });
  136. _saveSettings();
  137. },
  138. ),
  139. Divider(),
  140. ],
  141. );
  142. }
  143. Widget _buildVibrateSetting() {
  144. return Column(
  145. crossAxisAlignment: CrossAxisAlignment.start,
  146. children: [
  147. Padding(
  148. padding: const EdgeInsets.fromLTRB(16, 8, 16, 8),
  149. child: Row(
  150. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  151. children: [
  152. Text(
  153. 'Vibrate on ring',
  154. style: TextStyle(fontSize: 18),
  155. ),
  156. Switch(
  157. value: _vibrate,
  158. activeColor: Colors.orange,
  159. onChanged: (value) {
  160. setState(() {
  161. _vibrate = value;
  162. });
  163. _saveSettings();
  164. },
  165. ),
  166. ],
  167. ),
  168. ),
  169. Divider(),
  170. ],
  171. );
  172. }
  173. Widget _buildLoopSetting() {
  174. return Column(
  175. crossAxisAlignment: CrossAxisAlignment.start,
  176. children: [
  177. Padding(
  178. padding: const EdgeInsets.fromLTRB(16, 8, 16, 8),
  179. child: Row(
  180. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  181. children: [
  182. Text(
  183. 'Loop timer',
  184. style: TextStyle(fontSize: 18),
  185. ),
  186. Switch(
  187. value: _loop,
  188. activeColor: Colors.orange,
  189. onChanged: (value) {
  190. setState(() {
  191. _loop = value;
  192. // 如果循环被关闭,也关闭整点对齐
  193. if (!value) {
  194. _alignToHour = false;
  195. }
  196. });
  197. _saveSettings();
  198. },
  199. ),
  200. ],
  201. ),
  202. ),
  203. Divider(),
  204. ],
  205. );
  206. }
  207. Widget _buildAlignToHourSetting() {
  208. // 只有当倒计时满10分钟且启用了循环倒计时时才启用该选项
  209. bool isEnabled = _loop;
  210. return Column(
  211. crossAxisAlignment: CrossAxisAlignment.start,
  212. children: [
  213. Padding(
  214. padding: const EdgeInsets.fromLTRB(16, 8, 16, 8),
  215. child: Row(
  216. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  217. children: [
  218. Column(
  219. crossAxisAlignment: CrossAxisAlignment.start,
  220. children: [
  221. Text(
  222. '整点对齐',
  223. style: TextStyle(
  224. fontSize: 18,
  225. color: isEnabled ? Colors.black : Colors.grey,
  226. ),
  227. ),
  228. Text(
  229. '倒计时将等待整10分钟再开始',
  230. style: TextStyle(
  231. fontSize: 12,
  232. color: Colors.grey,
  233. ),
  234. ),
  235. ],
  236. ),
  237. Switch(
  238. value: _alignToHour && isEnabled,
  239. activeColor: Colors.orange,
  240. onChanged: isEnabled
  241. ? (value) {
  242. setState(() {
  243. _alignToHour = value;
  244. });
  245. _saveSettings();
  246. }
  247. : null,
  248. ),
  249. ],
  250. ),
  251. ),
  252. Divider(),
  253. ],
  254. );
  255. }
  256. void _showSoundPicker() {
  257. showModalBottomSheet(
  258. context: context,
  259. builder: (context) {
  260. return Column(
  261. mainAxisSize: MainAxisSize.min,
  262. children: _availableSounds.map((sound) {
  263. return ListTile(
  264. title: Text(sound),
  265. onTap: () {
  266. setState(() {
  267. _sound = sound;
  268. });
  269. _saveSettings();
  270. Navigator.pop(context);
  271. },
  272. trailing: _sound == sound
  273. ? Icon(Icons.check, color: Colors.blue)
  274. : null,
  275. );
  276. }).toList(),
  277. );
  278. },
  279. );
  280. }
  281. @override
  282. void dispose() {
  283. super.dispose();
  284. }
  285. }