settings_page.dart 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_screenutil/flutter_screenutil.dart';
  3. import 'package:get/get.dart';
  4. import 'package:gobang/controllers/game_controller.dart';
  5. import 'package:gobang/themes/app_colors.dart';
  6. import 'package:gobang/themes/black_theme_factory.dart';
  7. class SettingsPage extends StatelessWidget {
  8. const SettingsPage({super.key});
  9. @override
  10. Widget build(BuildContext context) {
  11. final c = Get.find<GameController>();
  12. return Scaffold(
  13. body: Container(
  14. width: double.infinity,
  15. decoration: const BoxDecoration(
  16. gradient: LinearGradient(
  17. begin: Alignment.topCenter,
  18. end: Alignment.bottomCenter,
  19. colors: [AppColors.ink, AppColors.mist],
  20. ),
  21. ),
  22. child: SafeArea(
  23. child: Padding(
  24. padding: EdgeInsets.fromLTRB(24.w, 16.h, 24.w, 24.h),
  25. child: Column(
  26. crossAxisAlignment: CrossAxisAlignment.start,
  27. children: [
  28. Row(
  29. children: [
  30. IconButton(
  31. onPressed: Get.back,
  32. icon: const Icon(Icons.arrow_back_ios_new_rounded,
  33. color: AppColors.ivory),
  34. ),
  35. Text(
  36. '设置 · 样式',
  37. style: TextStyle(
  38. color: AppColors.ivory,
  39. fontSize: 26.sp,
  40. fontWeight: FontWeight.w800,
  41. ),
  42. ),
  43. ],
  44. ),
  45. SizedBox(height: 6.h),
  46. Text(
  47. '主题 / 棋子 / 特效',
  48. style: TextStyle(
  49. color: AppColors.ivory.withValues(alpha: 0.7),
  50. fontSize: 13.sp,
  51. ),
  52. ),
  53. SizedBox(height: 20.h),
  54. Obx(() {
  55. final isDark = c.themeFactory.value is BlackThemeFactory;
  56. final circle = c.useCircle.value;
  57. return Column(
  58. children: [
  59. _Card(
  60. title: '主题色',
  61. child: Row(
  62. children: [
  63. _Swatch(
  64. color: AppColors.ink,
  65. selected: !isDark,
  66. onTap: () {
  67. if (isDark) c.toggleTheme();
  68. },
  69. ),
  70. SizedBox(width: 12.w),
  71. _Swatch(
  72. color: AppColors.darkBg,
  73. selected: isDark,
  74. onTap: () {
  75. if (!isDark) c.toggleTheme();
  76. },
  77. ),
  78. SizedBox(width: 12.w),
  79. const _Swatch(color: AppColors.pumpkin),
  80. SizedBox(width: 12.w),
  81. const _Swatch(color: AppColors.inkMid),
  82. ],
  83. ),
  84. ),
  85. SizedBox(height: 14.h),
  86. _Card(
  87. title: '棋子形状',
  88. child: Row(
  89. children: [
  90. _Chip(
  91. label: '圆形',
  92. selected: circle,
  93. onTap: () {
  94. if (!circle) c.toggleShape();
  95. },
  96. ),
  97. SizedBox(width: 12.w),
  98. _Chip(
  99. label: '方形',
  100. selected: !circle,
  101. onTap: () {
  102. if (circle) c.toggleShape();
  103. },
  104. ),
  105. ],
  106. ),
  107. ),
  108. SizedBox(height: 14.h),
  109. const _Card(
  110. title: '动效',
  111. child: Text(
  112. '落子缩放 · 脉冲高亮 · 胜负弹窗',
  113. style: TextStyle(
  114. color: Color(0xFF5A736A),
  115. fontSize: 13,
  116. ),
  117. ),
  118. ),
  119. ],
  120. );
  121. }),
  122. ],
  123. ),
  124. ),
  125. ),
  126. ),
  127. );
  128. }
  129. }
  130. class _Card extends StatelessWidget {
  131. const _Card({required this.title, required this.child});
  132. final String title;
  133. final Widget child;
  134. @override
  135. Widget build(BuildContext context) {
  136. return Container(
  137. width: double.infinity,
  138. padding: EdgeInsets.all(18.w),
  139. decoration: BoxDecoration(
  140. color: AppColors.ivory,
  141. borderRadius: BorderRadius.circular(20.r),
  142. ),
  143. child: Column(
  144. crossAxisAlignment: CrossAxisAlignment.start,
  145. children: [
  146. Text(
  147. title,
  148. style: TextStyle(
  149. color: AppColors.ink,
  150. fontSize: 15.sp,
  151. fontWeight: FontWeight.w700,
  152. ),
  153. ),
  154. SizedBox(height: 12.h),
  155. child,
  156. ],
  157. ),
  158. );
  159. }
  160. }
  161. class _Swatch extends StatelessWidget {
  162. const _Swatch({required this.color, this.selected = false, this.onTap});
  163. final Color color;
  164. final bool selected;
  165. final VoidCallback? onTap;
  166. @override
  167. Widget build(BuildContext context) {
  168. return GestureDetector(
  169. onTap: onTap,
  170. child: Container(
  171. width: 36.w,
  172. height: 36.w,
  173. decoration: BoxDecoration(
  174. color: color,
  175. shape: BoxShape.circle,
  176. border: Border.all(
  177. color: selected ? AppColors.pumpkin : Colors.white54,
  178. width: selected ? 3 : 1,
  179. ),
  180. ),
  181. ),
  182. );
  183. }
  184. }
  185. class _Chip extends StatelessWidget {
  186. const _Chip({
  187. required this.label,
  188. required this.selected,
  189. required this.onTap,
  190. });
  191. final String label;
  192. final bool selected;
  193. final VoidCallback onTap;
  194. @override
  195. Widget build(BuildContext context) {
  196. return GestureDetector(
  197. onTap: onTap,
  198. child: Container(
  199. padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 10.h),
  200. decoration: BoxDecoration(
  201. color: selected ? AppColors.ink : AppColors.mist,
  202. borderRadius: BorderRadius.circular(12.r),
  203. ),
  204. child: Text(
  205. label,
  206. style: TextStyle(
  207. color: selected ? AppColors.ivory : AppColors.ink,
  208. fontWeight: FontWeight.w600,
  209. fontSize: 13.sp,
  210. ),
  211. ),
  212. ),
  213. );
  214. }
  215. }