feat:更新TabUI模块
This commit is contained in:
@@ -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<StatefulWidget> createState() => _RecordPageState();
|
||||
}
|
||||
|
||||
class _RecordPageState extends State<RecordPage>
|
||||
with SingleTickerProviderStateMixin {
|
||||
|
||||
late final TabController _tabController = TabController(
|
||||
length: 3,
|
||||
vsync: this,
|
||||
);
|
||||
|
||||
final List<TDTab> 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<RecordPage> {
|
||||
RecordTab _currentTab = RecordTab.recipe;
|
||||
final List<Widget> _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<RecordTab> 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),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -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<T extends Enum>({
|
||||
required BuildContext context,
|
||||
required T currentTab,
|
||||
required List<T> tabValues,
|
||||
required List<String> labels,
|
||||
required ValueChanged<T> 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,
|
||||
|
||||
@@ -91,6 +91,7 @@ class _YearSelectorState extends State<YearSelector>
|
||||
circleIconButton(
|
||||
context: context,
|
||||
icon: Icons.chevron_left,
|
||||
isSmall: true,
|
||||
onPressed: () => _previousYear(),
|
||||
),
|
||||
SizedBox(width: 5),
|
||||
@@ -113,6 +114,7 @@ class _YearSelectorState extends State<YearSelector>
|
||||
circleIconButton(
|
||||
context: context,
|
||||
icon: Icons.chevron_right,
|
||||
isSmall: true,
|
||||
onPressed: () => _nextYear(),
|
||||
)
|
||||
],
|
||||
|
||||
@@ -114,13 +114,13 @@ class _RecipeCalendarState extends State<RecipeCalendar> {
|
||||
|
||||
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],
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -33,14 +33,11 @@ class _RecipeListState extends State<RecipeList> {
|
||||
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);
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user