import 'dart:async'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../../constants/app_constants.dart'; /// 时间: 2026-03-27 /// 功能: 主题个性化设置页面 /// 介绍: 允许用户自定义应用主题、颜色、字体大小等 class AppDiyPage extends StatefulWidget { const AppDiyPage({super.key}); @override State createState() => _AppDiyPageState(); } class _AppDiyPageState extends State { // 主题设置 bool _isDarkMode = false; int _themeColorIndex = 0; int _fontSizeIndex = 1; // 0: 小, 1: 中, 2: 大 bool _showGuideOnStartup = true; int _cardSizeIndex = 1; // 0: 小, 1: 中, 2: 大 bool _enableAnimation = true; bool _enableBlurEffect = true; bool _enableSystemNavigation = false; int _accentColorIndex = 0; // 滚动控制 final ScrollController _scrollController = ScrollController(); bool _isScrolling = true; late Timer _scrollTimer; // 主题颜色选项 final List _themeColors = [ AppConstants.primaryColor, // 默认紫色 Colors.blue, // 蓝色 Colors.green, // 绿色 Colors.orange, // 橙色 Colors.red, // 红色 Colors.teal, // 青色 ]; // 强调色选项 final List _accentColors = [ AppConstants.primaryColor, // 默认紫色 Colors.yellow, // 黄色 Colors.pink, // 粉色 Colors.cyan, // 青色 Colors.purple, // 深紫色 ]; // 字体大小选项 final List _fontSizes = ['小', '中', '大']; // 卡片大小选项 final List _cardSizes = ['小', '中', '大']; @override void initState() { super.initState(); _loadSettings(); _startScrolling(); // 延迟显示开发中提示对话框 WidgetsBinding.instance.addPostFrameCallback((_) { _showDevNoticeDialog(); }); } // 显示开发中提示对话框 void _showDevNoticeDialog() { showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return AlertDialog( title: Row( children: [ Icon(Icons.construction, color: AppConstants.primaryColor), const SizedBox(width: 8), const Text('开发中'), ], ), content: const Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '个性化设置开发中', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16), ), SizedBox(height: 12), Text('• 当前设置仅当前页面生效'), Text('• 后续版本将陆续支持'), Text('• 可提前预览主题风格设置'), SizedBox(height: 12), Text( '感谢您的耐心等待!', style: TextStyle(color: Colors.grey, fontSize: 12), ), ], ), actions: [ ElevatedButton( onPressed: () => Navigator.of(context).pop(), style: ElevatedButton.styleFrom( backgroundColor: AppConstants.primaryColor, foregroundColor: Colors.white, ), child: const Text('我知道了'), ), ], ); }, ); } @override void dispose() { _scrollController.dispose(); _scrollTimer.cancel(); super.dispose(); } void _startScrolling() { _isScrolling = true; _scrollTimer = Timer.periodic(const Duration(milliseconds: 30), (timer) { if (_scrollController.hasClients) { _scrollController.jumpTo(_scrollController.offset + 1); // 当滚动到末尾时,重新开始滚动 if (_scrollController.offset >= _scrollController.position.maxScrollExtent) { _scrollController.jumpTo(0); } } }); } void _stopScrolling() { _isScrolling = false; _scrollTimer.cancel(); } void _toggleScroll() { if (_isScrolling) { _stopScrolling(); } else { _startScrolling(); } } void _loadSettings() async { final prefs = await SharedPreferences.getInstance(); setState(() { _isDarkMode = prefs.getBool('darkMode') ?? false; _themeColorIndex = prefs.getInt('themeColorIndex') ?? 0; _fontSizeIndex = prefs.getInt('fontSizeIndex') ?? 1; _showGuideOnStartup = prefs.getBool('showGuideOnStartup') ?? true; _cardSizeIndex = prefs.getInt('cardSizeIndex') ?? 1; _enableAnimation = prefs.getBool('enableAnimation') ?? true; _enableBlurEffect = prefs.getBool('enableBlurEffect') ?? true; _enableSystemNavigation = prefs.getBool('enableSystemNavigation') ?? false; _accentColorIndex = prefs.getInt('accentColorIndex') ?? 0; }); } void _saveSettings() async { final prefs = await SharedPreferences.getInstance(); prefs.setBool('darkMode', _isDarkMode); prefs.setInt('themeColorIndex', _themeColorIndex); prefs.setInt('fontSizeIndex', _fontSizeIndex); prefs.setBool('showGuideOnStartup', _showGuideOnStartup); prefs.setInt('cardSizeIndex', _cardSizeIndex); prefs.setBool('enableAnimation', _enableAnimation); prefs.setBool('enableBlurEffect', _enableBlurEffect); prefs.setBool('enableSystemNavigation', _enableSystemNavigation); prefs.setInt('accentColorIndex', _accentColorIndex); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('个性化'), backgroundColor: _isDarkMode ? Colors.grey[900] : Colors.white, foregroundColor: _isDarkMode ? Colors.white : AppConstants.primaryColor, elevation: 0, ), backgroundColor: _isDarkMode ? Colors.grey[900] : Colors.grey[50], body: ListView( padding: const EdgeInsets.all(16), children: [ // 主题模式 _buildSection('显示设置'), _buildSwitchItem('深色模式', _isDarkMode, (value) { setState(() { _isDarkMode = value; _saveSettings(); }); }, icon: Icons.dark_mode), // 主题颜色 _buildSection('主题颜色'), _buildColorSelector('色彩', _themeColors, _themeColorIndex, (index) { setState(() { _themeColorIndex = index; _saveSettings(); }); }), _buildColorSelector('强调色', _accentColors, _accentColorIndex, (index) { setState(() { _accentColorIndex = index; _saveSettings(); }); }), // 字体大小 _buildSection('字体设置'), _buildOptionSelector('字体大小', _fontSizes, _fontSizeIndex, (index) { if (index != null) { setState(() { _fontSizeIndex = index; _saveSettings(); }); } }, icon: Icons.font_download), // 卡片大小 _buildSection('界面设置'), _buildOptionSelector('卡片阴影', _cardSizes, _cardSizeIndex, (index) { if (index != null) { setState(() { _cardSizeIndex = index; _saveSettings(); }); } }, icon: Icons.crop_square), // 启动显示 _buildSwitchItem('启动时显示引导页', _showGuideOnStartup, (value) { setState(() { _showGuideOnStartup = value; _saveSettings(); }); }, icon: Icons.info_outline), // 动画效果 _buildSwitchItem('启用动画效果', _enableAnimation, (value) { setState(() { _enableAnimation = value; _saveSettings(); }); }, icon: Icons.animation), // 模糊效果 _buildSwitchItem('启用模糊效果', _enableBlurEffect, (value) { setState(() { _enableBlurEffect = value; _saveSettings(); }); }, icon: Icons.blur_on), // 系统导航 _buildSwitchItem('软件悬浮球', _enableSystemNavigation, (value) { setState(() { _enableSystemNavigation = value; _saveSettings(); }); }, icon: Icons.navigation), _buildSwitchItem('转场动画', _enableAnimation, (value) { setState(() { // _enableAnimation = value; _saveSettings(); }); }, icon: Icons.track_changes), // 设计风格 _buildSection('设计风格'), _buildDesignStyleCard(), const SizedBox(height: 40), ], ), ); } Widget _buildSection(String title) { return Padding( padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 8), child: Text( title, style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: _isDarkMode ? Colors.grey[300] : Colors.grey[700], ), ), ); } Widget _buildSwitchItem( String title, bool value, ValueChanged onChanged, { required IconData icon, }) { return Container( margin: const EdgeInsets.symmetric(vertical: 4), decoration: BoxDecoration( color: _isDarkMode ? Colors.grey[800] : Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withAlpha(5), blurRadius: 2, offset: const Offset(0, 1), ), ], ), child: ListTile( leading: Icon(icon, color: _themeColors[_themeColorIndex]), title: Text( title, style: TextStyle(color: _isDarkMode ? Colors.white : Colors.black87), ), trailing: Switch( value: value, onChanged: onChanged, activeThumbColor: _themeColors[_themeColorIndex], ), ), ); } Widget _buildOptionSelector( String title, List options, int selectedIndex, ValueChanged onChanged, { required IconData icon, }) { return Container( margin: const EdgeInsets.symmetric(vertical: 4), decoration: BoxDecoration( color: _isDarkMode ? Colors.grey[800] : Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withAlpha(5), blurRadius: 2, offset: const Offset(0, 1), ), ], ), child: ListTile( leading: Icon(icon, color: _themeColors[_themeColorIndex]), title: Text( title, style: TextStyle(color: _isDarkMode ? Colors.white : Colors.black87), ), trailing: DropdownButton( value: selectedIndex, onChanged: (value) { if (value != null) { onChanged(value); } }, items: options.asMap().entries.map((entry) { return DropdownMenuItem( value: entry.key, child: Text( entry.value, style: TextStyle( color: _isDarkMode ? Colors.white : Colors.black87, ), ), ); }).toList(), dropdownColor: _isDarkMode ? Colors.grey[800] : Colors.white, style: TextStyle(color: _isDarkMode ? Colors.white : Colors.black87), ), ), ); } Widget _buildColorSelector( String title, List colors, int selectedIndex, ValueChanged onChanged, ) { return Container( margin: const EdgeInsets.symmetric(vertical: 4), decoration: BoxDecoration( color: _isDarkMode ? Colors.grey[800] : Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withAlpha(5), blurRadius: 2, offset: const Offset(0, 1), ), ], ), child: ListTile( title: Text( title, style: TextStyle(color: _isDarkMode ? Colors.white : Colors.black87), ), trailing: Row( mainAxisSize: MainAxisSize.min, children: colors.asMap().entries.map((entry) { return GestureDetector( onTap: () => onChanged(entry.key), child: Container( width: 32, height: 32, margin: const EdgeInsets.symmetric(horizontal: 4), decoration: BoxDecoration( color: entry.value, shape: BoxShape.circle, border: entry.key == selectedIndex ? Border.all( color: _isDarkMode ? Colors.white : Colors.black, width: 2, ) : null, ), ), ); }).toList(), ), ), ); } Widget _buildDesignStyleCard() { return Container( margin: const EdgeInsets.symmetric(vertical: 4), decoration: BoxDecoration( color: _isDarkMode ? Colors.grey[800] : Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withAlpha(5), blurRadius: 2, offset: const Offset(0, 1), ), ], ), child: Column( children: [ Padding( padding: const EdgeInsets.all(16), child: Row( children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.teal.withAlpha(10), borderRadius: BorderRadius.circular(8), ), child: Icon( Icons.design_services, color: _isDarkMode ? Colors.teal[300] : Colors.teal[700], size: 20, ), ), const SizedBox(width: 12), Text( '设计样式&主题风格', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: _isDarkMode ? Colors.white : Colors.black87, ), ), ], ), ), const Divider(height: 1), Padding( padding: const EdgeInsets.all(16), child: Column( children: [ GestureDetector( onTap: _toggleScroll, child: Container( height: 40, child: SingleChildScrollView( controller: _scrollController, scrollDirection: Axis.horizontal, child: Row( children: [ _buildStyleChip( 'Material 2', Icons.style, isMd: true, ), const SizedBox(width: 8), _buildStyleChip( 'Material 3', Icons.auto_awesome, isMd: true, ), const SizedBox(width: 8), _buildStyleChip('透明毛玻璃', Icons.blur_on), const SizedBox(width: 8), _buildStyleChip('沉浸式渐变色', Icons.color_lens), const SizedBox(width: 8), _buildStyleChip('动态光感效果', Icons.lightbulb_outline), const SizedBox(width: 8), ], ), ), ), ), const SizedBox(height: 12), Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( gradient: LinearGradient( colors: [ _themeColors[_themeColorIndex].withAlpha(10), _themeColors[_themeColorIndex].withAlpha(5), ], ), borderRadius: BorderRadius.circular(8), ), child: Row( children: [ Icon( Icons.lightbulb_outline, size: 16, color: _themeColors[_themeColorIndex], ), const SizedBox(width: 8), Expanded( child: Text( '采用现代Material Design设计语言,\n参考透明毛玻璃、沉浸式渐变色和动态光感等效果', style: TextStyle( fontSize: 12, color: _isDarkMode ? Colors.grey[300] : Colors.grey[700], ), ), ), ], ), ), ], ), ), ], ), ); } Widget _buildStyleChip(String label, IconData icon, {bool isMd = false}) { final color = isMd ? _themeColors[_themeColorIndex] : _isDarkMode ? Colors.blue[400]! : Colors.blue[600]!; return Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: color.withAlpha(10), borderRadius: BorderRadius.circular(16), border: Border.all(color: color.withAlpha(50), width: 1), ), child: Row( children: [ Icon(icon, size: 14, color: color), const SizedBox(width: 4), Text(label, style: TextStyle(fontSize: 12, color: color)), ], ), ); } }