feat:增加主题颜色和暗黑模式
This commit is contained in:
@@ -1,21 +1,24 @@
|
||||
import 'package:flisp_app/provider/app_provider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../provider/app_provider.dart';
|
||||
|
||||
class AppDrawer extends StatelessWidget {
|
||||
const AppDrawer({super.key});
|
||||
|
||||
DrawerHeader buildDrawerHeader() {
|
||||
DrawerHeader buildDrawerHeader(BuildContext context) {
|
||||
return DrawerHeader(
|
||||
decoration: BoxDecoration(color: Colors.blue.shade700),
|
||||
child: const Column(
|
||||
decoration: BoxDecoration(color: Theme.of(context).primaryColor),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
CircleAvatar(
|
||||
radius: 30,
|
||||
backgroundColor: Colors.white,
|
||||
child: Icon(Icons.flash_on, color: Colors.blue, size: 40),
|
||||
child: Icon(
|
||||
Icons.flash_on,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
size: 40,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Text(
|
||||
@@ -35,36 +38,170 @@ class AppDrawer extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDarkModeSection(BuildContext context, AppProvider appProvider) {
|
||||
return ListTile(
|
||||
leading: Icon(
|
||||
appProvider.isDarkMode ? Icons.dark_mode : Icons.light_mode,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
title: const Text('暗黑模式'),
|
||||
trailing: Switch(
|
||||
value: appProvider.isDarkMode,
|
||||
onChanged: (value) {
|
||||
appProvider.toggleDarkMode(value);
|
||||
},
|
||||
),
|
||||
onTap: () {
|
||||
appProvider.toggleDarkMode(!appProvider.isDarkMode);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildThemeColorList(BuildContext context, AppProvider appProvider) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
||||
child: GridView.builder(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 4,
|
||||
crossAxisSpacing: 8,
|
||||
mainAxisSpacing: 8,
|
||||
childAspectRatio: 1.2,
|
||||
),
|
||||
itemCount: appProvider.availableThemes.length,
|
||||
itemBuilder: (context, index) {
|
||||
final themeColor = appProvider.availableThemes[index];
|
||||
final isSelected = appProvider.currentTheme == themeColor;
|
||||
|
||||
return _buildThemeColorItem(
|
||||
themeColor: themeColor,
|
||||
isSelected: isSelected,
|
||||
onTap: () => appProvider.changeTheme(themeColor),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildThemeColorItem({
|
||||
required ThemeColor themeColor,
|
||||
required bool isSelected,
|
||||
required VoidCallback onTap,
|
||||
}) {
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
isSelected
|
||||
? themeColor.primaryColor.withAlpha(50)
|
||||
: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
color: isSelected ? themeColor.primaryColor : Colors.grey.shade300,
|
||||
width: isSelected ? 2 : 1,
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
// 颜色圆点
|
||||
Container(
|
||||
width: 20,
|
||||
height: 20,
|
||||
decoration: BoxDecoration(
|
||||
color: themeColor.primaryColor,
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: Colors.white, width: 2),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withAlpha(10),
|
||||
blurRadius: 2,
|
||||
offset: const Offset(0, 1),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
themeColor.name,
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
|
||||
color:
|
||||
isSelected ? themeColor.primaryColor : Colors.grey.shade600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildThemeSection(BuildContext context, AppProvider appProvider) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
|
||||
child: Text('主题颜色', style: Theme.of(context).textTheme.titleMedium),
|
||||
),
|
||||
_buildDarkModeSection(context, appProvider),
|
||||
_buildThemeColorList(context, appProvider),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// 构建抽屉菜单项
|
||||
Widget _buildDrawerItem({
|
||||
required BuildContext context,
|
||||
required IconData icon,
|
||||
required String title,
|
||||
required VoidCallback onTap,
|
||||
}) {
|
||||
return ListTile(
|
||||
leading: Icon(icon, color: Theme.of(context).colorScheme.primary),
|
||||
title: Text(title),
|
||||
onTap: onTap,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final appProvider = Provider.of<AppProvider>(context);
|
||||
|
||||
return Drawer(
|
||||
child: ListView(
|
||||
padding: EdgeInsets.zero,
|
||||
children: [
|
||||
// 抽屉头部
|
||||
buildDrawerHeader(),
|
||||
buildDrawerHeader(context),
|
||||
|
||||
// 菜单项
|
||||
_buildDrawerItem(
|
||||
context: context,
|
||||
icon: Icons.flash_on,
|
||||
title: '闪灵',
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
Provider.of<AppProvider>(context, listen: false).changeTab(0);
|
||||
appProvider.changeTab(0);
|
||||
},
|
||||
),
|
||||
_buildDrawerItem(
|
||||
context: context,
|
||||
icon: Icons.checklist,
|
||||
title: '待办事项',
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
Provider.of<AppProvider>(context, listen: false).changeTab(1);
|
||||
appProvider.changeTab(1);
|
||||
},
|
||||
),
|
||||
|
||||
const Divider(),
|
||||
|
||||
_buildDrawerItem(
|
||||
context: context,
|
||||
icon: Icons.analytics,
|
||||
title: '统计',
|
||||
onTap: () {
|
||||
@@ -73,6 +210,7 @@ class AppDrawer extends StatelessWidget {
|
||||
},
|
||||
),
|
||||
_buildDrawerItem(
|
||||
context: context,
|
||||
icon: Icons.archive,
|
||||
title: '归档',
|
||||
onTap: () {
|
||||
@@ -83,15 +221,12 @@ class AppDrawer extends StatelessWidget {
|
||||
|
||||
const Divider(),
|
||||
|
||||
_buildThemeSection(context, appProvider),
|
||||
|
||||
const Divider(),
|
||||
|
||||
_buildDrawerItem(
|
||||
icon: Icons.settings,
|
||||
title: '设置',
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
// 这里可以导航到设置页面
|
||||
},
|
||||
),
|
||||
_buildDrawerItem(
|
||||
context: context,
|
||||
icon: Icons.help,
|
||||
title: '帮助与反馈',
|
||||
onTap: () {
|
||||
@@ -103,17 +238,4 @@ class AppDrawer extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// 构建抽屉菜单项
|
||||
Widget _buildDrawerItem({
|
||||
required IconData icon,
|
||||
required String title,
|
||||
required VoidCallback onTap,
|
||||
}) {
|
||||
return ListTile(
|
||||
leading: Icon(icon, color: Colors.blue.shade600),
|
||||
title: Text(title),
|
||||
onTap: onTap,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,20 +28,38 @@ class _MainScreenState extends State<MainScreen> {
|
||||
return Scaffold(
|
||||
drawer: const AppDrawer(),
|
||||
appBar: AppBar(
|
||||
title: Text(_getAppBarTitle(appProvider.currentIndex)),
|
||||
backgroundColor: Colors.blue,
|
||||
foregroundColor: Colors.white,
|
||||
title: Text(_getAppBarTitle(appProvider.currentTab)),
|
||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||
foregroundColor: Theme.of(context).colorScheme.onPrimary,
|
||||
elevation: 0,
|
||||
),
|
||||
body: _buildPage(appProvider.currentIndex),
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
currentIndex: appProvider.currentIndex,
|
||||
onTap: (index) => appProvider.changeTab(index),
|
||||
type: BottomNavigationBarType.fixed,
|
||||
backgroundColor: Colors.white,
|
||||
items: navItems,
|
||||
body: _buildPage(appProvider.currentTab),
|
||||
bottomNavigationBar: Container(
|
||||
decoration: BoxDecoration(
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Theme.of(context).colorScheme.shadow.withAlpha(20),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, -2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: BottomNavigationBar(
|
||||
currentIndex: appProvider.currentTab,
|
||||
onTap: (index) => appProvider.changeTab(index),
|
||||
type: BottomNavigationBarType.fixed,
|
||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||
selectedItemColor: Theme.of(context).colorScheme.primary,
|
||||
unselectedItemColor: Theme.of(context).colorScheme.onSurface.withAlpha(120),
|
||||
showSelectedLabels: true,
|
||||
showUnselectedLabels: true,
|
||||
items: navItems,
|
||||
),
|
||||
),
|
||||
floatingActionButton: _buildFloatingButton(
|
||||
context,
|
||||
appProvider.currentTab,
|
||||
),
|
||||
floatingActionButton: _buildFloatingButton(appProvider.currentIndex),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -59,7 +77,7 @@ class _MainScreenState extends State<MainScreen> {
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildFloatingButton(int index) {
|
||||
Widget _buildFloatingButton(BuildContext context, int index) {
|
||||
return FloatingActionButton(
|
||||
onPressed: () => _onPressFloatingButton(index),
|
||||
backgroundColor: Colors.transparent,
|
||||
@@ -70,18 +88,7 @@ class _MainScreenState extends State<MainScreen> {
|
||||
height: 50,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
gradient: LinearGradient(
|
||||
colors: [Colors.orange.shade300, Colors.orange.shade500],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.orange.shade100,
|
||||
blurRadius: 12,
|
||||
offset: Offset(0, 6),
|
||||
),
|
||||
],
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
child: Icon(Icons.add, color: Colors.white, size: 36),
|
||||
),
|
||||
|
||||
@@ -11,7 +11,7 @@ import 'layout/main_screen.dart';
|
||||
import 'models/todo.dart';
|
||||
import 'provider/todo_provider.dart';
|
||||
|
||||
void main() async{
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
// 初始化提醒服务
|
||||
final notifyService = NotifyService();
|
||||
@@ -50,22 +50,23 @@ class MyApp extends StatelessWidget {
|
||||
providers: [
|
||||
ChangeNotifierProvider(create: (_) => AppProvider()),
|
||||
ChangeNotifierProvider(create: (_) => TodoProvider()),
|
||||
ChangeNotifierProvider(create: (_) => FlispProvider())
|
||||
ChangeNotifierProvider(create: (_) => FlispProvider()),
|
||||
],
|
||||
child: MaterialApp(
|
||||
title: '闪灵',
|
||||
localizationsDelegates: [
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate
|
||||
],
|
||||
supportedLocales: [
|
||||
const Locale('zh'),
|
||||
const Locale('zh', 'CN'),
|
||||
],
|
||||
locale: Locale('zh', 'CN'),
|
||||
theme: ThemeData(primarySwatch: Colors.blue, useMaterial3: true),
|
||||
home: const MainScreen(),
|
||||
child: Consumer<AppProvider>(
|
||||
builder: (context, appProvider, child) {
|
||||
return MaterialApp(
|
||||
title: '闪灵',
|
||||
localizationsDelegates: [
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
],
|
||||
supportedLocales: [const Locale('zh'), const Locale('zh', 'CN')],
|
||||
locale: Locale('zh', 'CN'),
|
||||
theme: appProvider.currentThemeData,
|
||||
home: const MainScreen(),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -40,11 +40,13 @@ class FlispPageState extends State<FlispPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return buildBody(
|
||||
return Padding(
|
||||
padding: EdgeInsets.all(10),
|
||||
child: Column(
|
||||
children: [
|
||||
buildStatsCard(_activeFlisps),
|
||||
buildTabs(
|
||||
context: context,
|
||||
currentTab: _currentTab,
|
||||
onTabChanged: (value) {
|
||||
setState(() {
|
||||
@@ -53,15 +55,15 @@ class FlispPageState extends State<FlispPage> {
|
||||
},
|
||||
),
|
||||
// 待办事项列表
|
||||
Expanded(child: _buildActiveFlispList()),
|
||||
Expanded(child: _buildActiveFlispList(context)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildActiveFlispList() {
|
||||
Widget _buildActiveFlispList(BuildContext context) {
|
||||
return _activeFlisps.isEmpty
|
||||
? buildEmptyState()
|
||||
? buildEmptyState(context)
|
||||
: buildFlispList(
|
||||
context: context,
|
||||
flisps: _activeFlisps,
|
||||
|
||||
@@ -42,11 +42,13 @@ class TodoPageState extends State<TodoPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return buildBody(
|
||||
return Padding(
|
||||
padding: EdgeInsets.all(10),
|
||||
child: Column(
|
||||
children: [
|
||||
buildStatsCard(_todos),
|
||||
buildTabs(
|
||||
context: context,
|
||||
currentTab: _currentTab,
|
||||
onTabChanged: (value) {
|
||||
setState(() {
|
||||
@@ -55,15 +57,15 @@ class TodoPageState extends State<TodoPage> {
|
||||
},
|
||||
),
|
||||
// 待办事项列表
|
||||
Expanded(child: _buildActiveTodoList()),
|
||||
Expanded(child: _buildActiveTodoList(context)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildActiveTodoList() {
|
||||
Widget _buildActiveTodoList(BuildContext context) {
|
||||
return _activeTodos.isEmpty
|
||||
? buildEmptyState(_currentTab)
|
||||
? buildEmptyState(context, _currentTab)
|
||||
: buildTodoList(
|
||||
todos: _activeTodos,
|
||||
onToggleTodo: (todo) {
|
||||
|
||||
@@ -1,12 +1,188 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AppProvider with ChangeNotifier {
|
||||
int _currentIndex = 0;
|
||||
class ThemeColor {
|
||||
final String name;
|
||||
final Color primaryColor;
|
||||
final MaterialColor materialColor;
|
||||
|
||||
int get currentIndex => _currentIndex;
|
||||
ThemeColor({
|
||||
required this.name,
|
||||
required this.primaryColor,
|
||||
required this.materialColor,
|
||||
});
|
||||
}
|
||||
|
||||
class AppProvider with ChangeNotifier {
|
||||
int _currentTab = 0;
|
||||
bool _isDarkMode = false;
|
||||
ThemeColor _currentTheme = _defaultThemes[0];
|
||||
|
||||
// 预定义主题色
|
||||
static final List<ThemeColor> _defaultThemes = [
|
||||
ThemeColor(
|
||||
name: '科技蓝',
|
||||
primaryColor: Color(0xFF2563EB),
|
||||
materialColor: MaterialColor(0xFF2563EB, {
|
||||
50: Color(0xFFDBEAFE),
|
||||
100: Color(0xFFBFDBFE),
|
||||
200: Color(0xFF93C5FD),
|
||||
300: Color(0xFF60A5FA),
|
||||
400: Color(0xFF3B82F6),
|
||||
500: Color(0xFF2563EB),
|
||||
600: Color(0xFF1D4ED8),
|
||||
700: Color(0xFF1E40AF),
|
||||
800: Color(0xFF1E3A8A),
|
||||
900: Color(0xFF1E3A8A),
|
||||
}),
|
||||
),
|
||||
ThemeColor(
|
||||
name: '翡翠绿',
|
||||
primaryColor: Color(0xFF10B981),
|
||||
materialColor: MaterialColor(0xFF10B981, {
|
||||
50: Color(0xFFECFDF5),
|
||||
100: Color(0xFFD1FAE5),
|
||||
200: Color(0xFFA7F3D0),
|
||||
300: Color(0xFF6EE7B7),
|
||||
400: Color(0xFF34D399),
|
||||
500: Color(0xFF10B981),
|
||||
600: Color(0xFF059669),
|
||||
700: Color(0xFF047857),
|
||||
800: Color(0xFF065F46),
|
||||
900: Color(0xFF064E3B),
|
||||
}),
|
||||
),
|
||||
ThemeColor(
|
||||
name: '活力橙',
|
||||
primaryColor: Color(0xFFF59E0B),
|
||||
materialColor: MaterialColor(0xFFF59E0B, {
|
||||
50: Color(0xFFFFFBEB),
|
||||
100: Color(0xFFFEF3C7),
|
||||
200: Color(0xFFFDE68A),
|
||||
300: Color(0xFFFCD34D),
|
||||
400: Color(0xFFFBBF24),
|
||||
500: Color(0xFFF59E0B),
|
||||
600: Color(0xFFD97706),
|
||||
700: Color(0xFFB45309),
|
||||
800: Color(0xFF92400E),
|
||||
900: Color(0xFF78350F),
|
||||
}),
|
||||
),
|
||||
ThemeColor(
|
||||
name: '梦幻紫',
|
||||
primaryColor: Color(0xFF8B5CF6),
|
||||
materialColor: MaterialColor(0xFF8B5CF6, {
|
||||
50: Color(0xFFF5F3FF),
|
||||
100: Color(0xFFEDE9FE),
|
||||
200: Color(0xFFDDD6FE),
|
||||
300: Color(0xFFC4B5FD),
|
||||
400: Color(0xFFA78BFA),
|
||||
500: Color(0xFF8B5CF6),
|
||||
600: Color(0xFF7C3AED),
|
||||
700: Color(0xFF6D28D9),
|
||||
800: Color(0xFF5B21B6),
|
||||
900: Color(0xFF4C1D95),
|
||||
}),
|
||||
),
|
||||
ThemeColor(
|
||||
name: '浪漫粉',
|
||||
primaryColor: Color(0xFFEC4899),
|
||||
materialColor: MaterialColor(0xFFEC4899, {
|
||||
50: Color(0xFFFDF2F8),
|
||||
100: Color(0xFFFCE7F3),
|
||||
200: Color(0xFFFBCFE8),
|
||||
300: Color(0xFFF9A8D4),
|
||||
400: Color(0xFFF472B6),
|
||||
500: Color(0xFFEC4899),
|
||||
600: Color(0xFFDB2777),
|
||||
700: Color(0xFFBE185D),
|
||||
800: Color(0xFF9D174D),
|
||||
900: Color(0xFF831843),
|
||||
}),
|
||||
),
|
||||
ThemeColor(
|
||||
name: '清新青',
|
||||
primaryColor: Color(0xFF06B6D4),
|
||||
materialColor: MaterialColor(0xFF06B6D4, {
|
||||
50: Color(0xFFF0FDFA),
|
||||
100: Color(0xFFCCFBF1),
|
||||
200: Color(0xFF99F6E4),
|
||||
300: Color(0xFF5EEAD4),
|
||||
400: Color(0xFF2DD4BF),
|
||||
500: Color(0xFF06B6D4),
|
||||
600: Color(0xFF0891B2),
|
||||
700: Color(0xFF0E7490),
|
||||
800: Color(0xFF155E75),
|
||||
900: Color(0xFF164E63),
|
||||
}),
|
||||
),
|
||||
ThemeColor(
|
||||
name: '深空蓝',
|
||||
primaryColor: Color(0xFF1E40AF),
|
||||
materialColor: MaterialColor(0xFF1E40AF, {
|
||||
50: Color(0xFFEFF6FF),
|
||||
100: Color(0xFFDBEAFE),
|
||||
200: Color(0xFFBFDBFE),
|
||||
300: Color(0xFF93C5FD),
|
||||
400: Color(0xFF60A5FA),
|
||||
500: Color(0xFF3B82F6),
|
||||
600: Color(0xFF2563EB),
|
||||
700: Color(0xFF1D4ED8),
|
||||
800: Color(0xFF1E40AF),
|
||||
900: Color(0xFF1E3A8A),
|
||||
}),
|
||||
),
|
||||
ThemeColor(
|
||||
name: '落日红',
|
||||
primaryColor: Color(0xFFEF4444),
|
||||
materialColor: MaterialColor(0xFFEF4444, {
|
||||
50: Color(0xFFFEF2F2),
|
||||
100: Color(0xFFFEE2E2),
|
||||
200: Color(0xFFFECACA),
|
||||
300: Color(0xFFFCA5A5),
|
||||
400: Color(0xFFF87171),
|
||||
500: Color(0xFFEF4444),
|
||||
600: Color(0xFFDC2626),
|
||||
700: Color(0xFFB91C1C),
|
||||
800: Color(0xFF991B1B),
|
||||
900: Color(0xFF7F1D1D),
|
||||
}),
|
||||
),
|
||||
];
|
||||
|
||||
int get currentTab => _currentTab;
|
||||
|
||||
bool get isDarkMode => _isDarkMode;
|
||||
|
||||
ThemeColor get currentTheme => _currentTheme;
|
||||
|
||||
List<ThemeColor> get availableThemes => _defaultThemes;
|
||||
|
||||
void changeTab(int index) {
|
||||
_currentIndex = index;
|
||||
_currentTab = index;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// 切换明暗模式
|
||||
void toggleDarkMode(bool value) {
|
||||
_isDarkMode = value;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// 更改主题色
|
||||
void changeTheme(ThemeColor theme) {
|
||||
_currentTheme = theme;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
ThemeData get currentThemeData {
|
||||
return ThemeData(
|
||||
primarySwatch: _currentTheme.materialColor,
|
||||
colorScheme: ColorScheme.fromSeed(
|
||||
seedColor: _currentTheme.primaryColor,
|
||||
brightness: _isDarkMode ? Brightness.dark : Brightness.light,
|
||||
),
|
||||
useMaterial3: true,
|
||||
fontFamily: 'CustomFont',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ void showAwesomeDialog({
|
||||
onPressed: onOk,
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.orange,
|
||||
backgroundColor: Theme.of(context).primaryColor,
|
||||
foregroundColor: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
@@ -61,7 +61,7 @@ void showErrorDialog(BuildContext context, String message) {
|
||||
animType: AnimType.scale,
|
||||
title: message,
|
||||
btnOkText: "好的",
|
||||
btnOkColor: Colors.green,
|
||||
btnOkColor: Colors.red,
|
||||
btnOkOnPress: () {},
|
||||
autoHide: Duration(seconds: 2),
|
||||
).show();
|
||||
|
||||
@@ -8,21 +8,25 @@ BoxDecoration buildBoxDecoration() {
|
||||
);
|
||||
}
|
||||
|
||||
Container buildBody({Widget? child}) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
color: Colors.grey[50],
|
||||
padding: EdgeInsets.all(8),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
class BuildCard extends StatelessWidget {
|
||||
final Widget? child;
|
||||
|
||||
Container buildCard({Widget? child}) {
|
||||
return Container(
|
||||
decoration: buildBoxDecoration(),
|
||||
padding: EdgeInsets.all(10),
|
||||
child: child,
|
||||
);
|
||||
const BuildCard({super.key, this.child});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colors = Theme.of(context).colorScheme;
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: colors.surface,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(color: colors.outline.withAlpha(50), width: 1),
|
||||
),
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void buildModalBottom({
|
||||
|
||||
@@ -11,7 +11,7 @@ Widget buildStatsCard(List<Flisp> flisps) {
|
||||
int workCount = flisps.where((flisp) => flisp.tag == FlispTag.work).length;
|
||||
int studyCount = flisps.where((flisp) => flisp.tag == FlispTag.study).length;
|
||||
|
||||
return buildCard(
|
||||
return BuildCard(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
@@ -42,6 +42,7 @@ Widget _buildStatItem(String label, int count, Color color) {
|
||||
}
|
||||
|
||||
Widget buildTabs({
|
||||
required BuildContext context,
|
||||
required FlispTab currentTab,
|
||||
required ValueChanged<FlispTab> onTabChanged,
|
||||
}) {
|
||||
@@ -53,7 +54,7 @@ Widget buildTabs({
|
||||
initialLabelIndex: FlispTab.values.indexOf(currentTab),
|
||||
totalSwitches: FlispTab.values.length,
|
||||
labels: FlispTab.values.map((e) => e.label).toList(),
|
||||
activeBgColor: [Colors.orange.shade600],
|
||||
activeBgColor: [Theme.of(context).colorScheme.primary],
|
||||
activeFgColor: Colors.white,
|
||||
inactiveBgColor: Colors.grey.shade200,
|
||||
inactiveFgColor: Colors.grey.shade700,
|
||||
@@ -89,11 +90,15 @@ Widget buildFlispList({
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFlispContent(Flisp flisp) {
|
||||
Widget _buildFlispContent(BuildContext context, Flisp flisp) {
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
text: flisp.content,
|
||||
style: const TextStyle(color: Colors.black87, fontSize: 16),
|
||||
style: TextStyle(
|
||||
fontFamily: 'CustomFont',
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -281,15 +286,13 @@ Widget _buildFlispItem({
|
||||
onDismissed: (direction) {
|
||||
onDelete(flisp);
|
||||
},
|
||||
child: Container(
|
||||
decoration: buildBoxDecoration(),
|
||||
padding: EdgeInsets.all(16),
|
||||
child: BuildCard(
|
||||
child: InkWell(
|
||||
onTap: () => onEdit(flisp),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildFlispContent(flisp),
|
||||
_buildFlispContent(context, flisp),
|
||||
const SizedBox(height: 8),
|
||||
if (hasImage) buildFlispImage(flisp: flisp, showDelete: false),
|
||||
const SizedBox(height: 4),
|
||||
@@ -337,16 +340,19 @@ Widget _buildDismissBackground() {
|
||||
}
|
||||
|
||||
// 空状态
|
||||
Widget buildEmptyState() {
|
||||
Widget buildEmptyState(BuildContext context) {
|
||||
final colors = Theme.of(context).colorScheme;
|
||||
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.flash_on, size: 80, color: Colors.orange.shade600),
|
||||
Icon(Icons.flash_on, size: 80, color: colors.primary),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'📝 还没有闪灵\n点击➕号添加第一个灵感吧~',
|
||||
'📝 还没有该类别闪灵\n点击➕号添加第一个灵感吧~',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: Colors.orange.shade600),
|
||||
style: TextStyle(color: colors.onSurface, fontSize: 16),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -38,7 +38,7 @@ class _TodoFormState extends State<TodoForm> {
|
||||
children: [
|
||||
Icon(
|
||||
widget.isEditing ? Icons.edit_note : Icons.add_task,
|
||||
color: Colors.orange,
|
||||
color: Theme.of(context).primaryColor,
|
||||
size: 24,
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
@@ -47,7 +47,7 @@ class _TodoFormState extends State<TodoForm> {
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.orange,
|
||||
color: Theme.of(context).primaryColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -13,7 +13,7 @@ Widget buildStatsCard(List<Todo> todos) {
|
||||
|
||||
int completedCount = todos.where((todo) => todo.isCompleted).length;
|
||||
|
||||
return buildCard(
|
||||
return BuildCard(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
@@ -44,6 +44,7 @@ Widget _buildStatItem(String label, int count, Color color) {
|
||||
|
||||
// Tab页
|
||||
Widget buildTabs({
|
||||
required BuildContext context,
|
||||
required TodoTab currentTab,
|
||||
required ValueChanged<TodoTab> onTabChanged,
|
||||
}) {
|
||||
@@ -55,7 +56,7 @@ Widget buildTabs({
|
||||
initialLabelIndex: TodoTab.values.indexOf(currentTab),
|
||||
totalSwitches: TodoTab.values.length,
|
||||
labels: TodoTab.values.map((e) => e.label).toList(),
|
||||
activeBgColor: [Colors.orange.shade600],
|
||||
activeBgColor: [Theme.of(context).colorScheme.primary],
|
||||
activeFgColor: Colors.white,
|
||||
inactiveBgColor: Colors.grey.shade200,
|
||||
inactiveFgColor: Colors.grey.shade700,
|
||||
@@ -94,7 +95,7 @@ Widget _buildTodoItem({
|
||||
required ValueChanged<Todo> onToggle,
|
||||
required ValueChanged<Todo> onEdit,
|
||||
}) {
|
||||
return buildCard(
|
||||
return BuildCard(
|
||||
child: ListTile(
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 8, vertical: 0),
|
||||
leading: SizedBox(
|
||||
@@ -267,7 +268,7 @@ Widget _buildPriorityBadge(TodoPriority priority) {
|
||||
}
|
||||
|
||||
// 空状态
|
||||
Widget buildEmptyState(TodoTab tab) {
|
||||
Widget buildEmptyState(BuildContext context, TodoTab tab) {
|
||||
final messages = {
|
||||
TodoTab.all: '📝 还没有待办事项\n点击➕号添加第一个任务吧~',
|
||||
TodoTab.active: '🎯 没有待完成的任务\n享受轻松时光吧!✨',
|
||||
@@ -275,15 +276,18 @@ Widget buildEmptyState(TodoTab tab) {
|
||||
TodoTab.today: '📅 今天没有安排任务\n好好放松一下吧~😊',
|
||||
};
|
||||
|
||||
final colors = Theme.of(context).colorScheme;
|
||||
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.checklist, size: 80, color: Colors.orange.shade600),
|
||||
Icon(Icons.checklist, size: 80, color: colors.primary),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
messages[tab] ?? '暂无数据',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: Colors.orange.shade600),
|
||||
style: TextStyle(color: colors.onSurface, fontSize: 16),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user