diff --git a/lib/views/record.dart b/lib/views/record.dart index 8169bb9..e138afb 100644 --- a/lib/views/record.dart +++ b/lib/views/record.dart @@ -1,9 +1,18 @@ import 'package:flutter/material.dart'; +import 'package:food_hub_app/widgets/common/index.dart'; import 'package:food_hub_app/widgets/recipe/calendar.dart'; import 'package:food_hub_app/widgets/recipe/list.dart'; import 'package:food_hub_app/widgets/recipe/timeline.dart'; -import 'package:tdesign_flutter/tdesign_flutter.dart'; +enum RecordTab { + recipe('菜谱'), + calendar('日历'), + timeline('时间轴'); + + final String label; + + const RecordTab(this.label); +} class RecordPage extends StatefulWidget { const RecordPage({super.key}); @@ -12,51 +21,46 @@ class RecordPage extends StatefulWidget { State createState() => _RecordPageState(); } -class _RecordPageState extends State - with SingleTickerProviderStateMixin { - - late final TabController _tabController = TabController( - length: 3, - vsync: this, - ); - - final List tabs = [ - const TDTab(text: '菜谱', icon: Icon(Icons.book)), - const TDTab(text: '日历', icon: Icon(Icons.calendar_month)), - const TDTab(text: '时间轴', icon: Icon(Icons.timeline)), +class _RecordPageState extends State { + RecordTab _currentTab = RecordTab.recipe; + final List _tabPages = [ + RecipeList(), + RecipeCalendar(), + RecipeTimeline(), ]; - @override - void initState() { - super.initState(); - } - - @override - void dispose() { - _tabController.dispose(); - super.dispose(); + Widget buildTabs({ + required BuildContext context, + required RecordTab currentTab, + required ValueChanged onTabChanged, + }) { + return Container( + padding: EdgeInsets.all(8), + child: buildToggleSwitch( + context: context, + currentTab: currentTab, + tabValues: RecordTab.values, + labels: RecordTab.values.map((e) => e.label).toList(), + onTabChanged: onTabChanged, + ), + ); } @override Widget build(BuildContext context) { return Column( children: [ - TDTabBar( - tabs: tabs, - controller: _tabController, - backgroundColor: Colors.white, - showIndicator: true, + buildTabs( + context: context, + currentTab: _currentTab, + onTabChanged: (tab) { + setState(() { + _currentTab = tab; + }); + }, ), - SizedBox(height: 8), Expanded( - child: TabBarView( - controller: _tabController, - children: [ - RecipeList(), - RecipeCalendar(), - RecipeTimeline(), - ], - ), + child: IndexedStack(index: _currentTab.index, children: _tabPages), ), ], ); diff --git a/lib/widgets/common/index.dart b/lib/widgets/common/index.dart index 1f06a9d..d088d62 100644 --- a/lib/widgets/common/index.dart +++ b/lib/widgets/common/index.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; +import 'package:toggle_switch/toggle_switch.dart'; Widget formLabelText({required String labelText, bool isRequired = false}) { return Text.rich( @@ -50,16 +51,46 @@ Widget buildEmptyData() { ); } +Widget buildToggleSwitch({ + required BuildContext context, + required T currentTab, + required List tabValues, + required List labels, + required ValueChanged onTabChanged, +}) { + return ToggleSwitch( + minWidth: 90.0, + minHeight: 40.0, + initialLabelIndex: tabValues.indexOf(currentTab), + totalSwitches: tabValues.length, + labels: labels, + activeBgColor: [Theme.of(context).colorScheme.primary], + activeFgColor: Colors.white, + inactiveBgColor: Colors.grey.shade200, + inactiveFgColor: Colors.grey.shade700, + cornerRadius: 12.0, + customTextStyles: [TextStyle(fontSize: 12, fontWeight: FontWeight.w500)], + onToggle: (index) { + if (index != null && index < tabValues.length) { + onTabChanged(tabValues[index]); + } + }, + ); +} + /// 圆形图标按钮 Widget circleIconButton({ required IconData icon, required VoidCallback onPressed, required BuildContext context, + bool? isSmall }) { + final double size = isSmall == true ? 24 : 36; + return ElevatedButton( onPressed: onPressed, style: ElevatedButton.styleFrom( - fixedSize: Size(26, 26), + fixedSize: Size(size, size), shape: CircleBorder(), elevation: 0, backgroundColor: Theme.of(context).colorScheme.primary, diff --git a/lib/widgets/common/year_selector.dart b/lib/widgets/common/year_selector.dart index 5c49296..09dfa2a 100644 --- a/lib/widgets/common/year_selector.dart +++ b/lib/widgets/common/year_selector.dart @@ -91,6 +91,7 @@ class _YearSelectorState extends State circleIconButton( context: context, icon: Icons.chevron_left, + isSmall: true, onPressed: () => _previousYear(), ), SizedBox(width: 5), @@ -113,6 +114,7 @@ class _YearSelectorState extends State circleIconButton( context: context, icon: Icons.chevron_right, + isSmall: true, onPressed: () => _nextYear(), ) ], diff --git a/lib/widgets/recipe/calendar.dart b/lib/widgets/recipe/calendar.dart index e1ce1a7..7323304 100644 --- a/lib/widgets/recipe/calendar.dart +++ b/lib/widgets/recipe/calendar.dart @@ -114,13 +114,13 @@ class _RecipeCalendarState extends State { return Card( elevation: 0, - color: colors.inversePrimary, + color: colors.onSecondary, child: Padding( padding: EdgeInsets.all(10), child: Row( children: [ CircleAvatar( - radius: 24, + radius: 20, backgroundColor: colors.primary, child: Text( record.category[0], diff --git a/lib/widgets/recipe/card.dart b/lib/widgets/recipe/card.dart index 9262b09..bfc3268 100644 --- a/lib/widgets/recipe/card.dart +++ b/lib/widgets/recipe/card.dart @@ -39,7 +39,7 @@ class RecipeCard extends StatelessWidget { icon: Icons.edit, onPressed: () => {}, ), - SizedBox(width: 8), + SizedBox(width: 4), circleIconButton( context: context, icon: Icons.book, @@ -54,7 +54,6 @@ class RecipeCard extends StatelessWidget { ), ], ), - const SizedBox(height: 5), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, diff --git a/lib/widgets/recipe/list.dart b/lib/widgets/recipe/list.dart index ce7d7ee..fb46f56 100644 --- a/lib/widgets/recipe/list.dart +++ b/lib/widgets/recipe/list.dart @@ -33,14 +33,11 @@ class _RecipeListState extends State { if (recipeSummaryList.isEmpty) { return buildEmptyData(); } else { - return ListView.separated( + return ListView.builder( itemCount: recipeSummaryList.length, itemBuilder: (context, index) { return RecipeCard(recipe: recipeSummaryList[index]); - }, - separatorBuilder: (context, index) { - return SizedBox(height: 10); - }, + } ); } } diff --git a/lib/widgets/recipe/timeline.dart b/lib/widgets/recipe/timeline.dart index 8284a0c..4f84409 100644 --- a/lib/widgets/recipe/timeline.dart +++ b/lib/widgets/recipe/timeline.dart @@ -5,7 +5,6 @@ import 'package:food_hub_app/models/recipe.dart'; import 'package:food_hub_app/widgets/common/image.dart'; import 'package:food_hub_app/widgets/common/index.dart'; import 'package:food_hub_app/widgets/common/year_selector.dart'; -import 'package:tdesign_flutter/tdesign_flutter.dart'; import 'package:timelines_plus/timelines_plus.dart'; class RecipeTimeline extends StatefulWidget { diff --git a/pubspec.lock b/pubspec.lock index 3944e5a..2b6017f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -906,6 +906,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.0.2" + toggle_switch: + dependency: "direct main" + description: + name: toggle_switch + sha256: dca04512d7c23ed320d6c5ede1211a404f177d54d353bf785b07d15546a86ce5 + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.3.0" typed_data: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index f5a366d..c83201b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -38,6 +38,7 @@ dependencies: dio: ^5.7.0 timelines_plus: ^1.0.7 table_calendar: ^3.1.3 + toggle_switch: ^2.3.0 flutter_form_builder: ^10.0.0 form_builder_validators: ^11.1.2 intl: ^0.19.0