import 'package:flutter/material.dart'; import 'package:toggle_switch/toggle_switch.dart'; OutlineInputBorder buildFormBoard() { return OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.grey.shade200), ); } OutlineInputBorder buildFormEnabledBoard() { return OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.grey.shade200), ); } OutlineInputBorder buildFormFocusedBoard(ColorScheme colors) { return OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: colors.primary), ); } // 卡片 class BuildCard extends StatelessWidget { final Widget? child; const BuildCard({super.key, this.child}); @override Widget build(BuildContext context) { final colors = Theme.of(context).colorScheme; return Container( decoration: BoxDecoration( color: colors.surfaceContainer, borderRadius: BorderRadius.circular(12), // border: Border.all(color: colors.outline.withAlpha(50), width: 1), ), padding: const EdgeInsets.all(16), child: child, ); } } // 底部弹出 void buildModalBottom({ required BuildContext context, required String title, required Widget body, }) { final colors = Theme.of(context).colorScheme; showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: Colors.transparent, builder: (BuildContext context) { return GestureDetector( onTap: () => Navigator.of(context).pop(), child: Container( color: Color.fromRGBO(0, 0, 0, 0.001), child: GestureDetector( onTap: () {}, child: DraggableScrollableSheet( initialChildSize: 0.6, minChildSize: 0.4, maxChildSize: 0.9, builder: (_, controller) { return Container( decoration: BoxDecoration( color: colors.surfaceContainer, border: Border.all( color: colors.outline.withAlpha(50), width: 1, ), borderRadius: BorderRadius.only( topLeft: Radius.circular(24), topRight: Radius.circular(24), ), ), child: buildModalBottomBody(context, title, body), ); }, ), ), ), ); }, ); } Widget buildModalBottomTitle(BuildContext context, String title) { return Padding( padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( title, style: TextStyle( fontSize: 20, color: Theme.of(context).colorScheme.primary, fontWeight: FontWeight.w700, ), ), ], ), ); } Widget buildModalBottomBody(BuildContext context, String title, Widget body) { return Column( children: [ // 拖拽指示条 Container( margin: EdgeInsets.only(top: 12, bottom: 4), width: 48, height: 4, decoration: BoxDecoration( color: Colors.grey[400], borderRadius: BorderRadius.circular(2), ), ), buildModalBottomTitle(context, title), Divider(height: 1, thickness: 1), Expanded(child: Padding(padding: EdgeInsets.all(12), child: body)), ], ); } // 滑动删除 Widget buildDismissible({ required BuildContext context, required Object id, required Widget child, required VoidCallback onDelete, }) { return Dismissible( key: ValueKey(id), direction: DismissDirection.endToStart, background: _buildDismissBackground(), confirmDismiss: (direction) async { // 这里实现二次确认 return await showDeleteConfirmationDialog(context); }, onDismissed: (direction) { onDelete(); }, child: child, ); } // 确认对话框 Future showDeleteConfirmationDialog(BuildContext context) async { return showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: const Text('确认删除'), backgroundColor: Theme.of(context).colorScheme.surfaceContainer, content: const Text('确定要删除这个项目吗?'), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), child: const Text('取消'), ), TextButton( onPressed: () => Navigator.of(context).pop(true), child: const Text('删除', style: TextStyle(color: Colors.red)), ), ], ); }, ); } Widget _buildDismissBackground() { return Container( color: Colors.red, alignment: Alignment.centerRight, padding: const EdgeInsets.only(right: 20), child: const Icon(Icons.delete, color: Colors.white, size: 24), ); } // toggle切换 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]); } }, ); } ButtonStyle buildSegmentStyle(ColorScheme colors) { return ButtonStyle( side: WidgetStateProperty.all( const BorderSide(color: Colors.transparent, width: 0), ), iconColor: WidgetStateProperty.resolveWith( (Set states) { if (states.contains(WidgetState.selected)) { return colors.onPrimary; } return Colors.grey; }, ), backgroundColor: WidgetStateProperty.resolveWith(( Set states, ) { if (states.contains(WidgetState.selected)) { return colors.primary; } return Colors.grey.shade200; }), foregroundColor: WidgetStateProperty.resolveWith(( Set states, ) { if (states.contains(WidgetState.selected)) { return colors.onPrimary; } return colors.onSurface; }), shape: WidgetStateProperty.all( RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), ), ); } Widget circleIconButton({ required IconData icon, required VoidCallback onPressed, required BuildContext context, }) { return ElevatedButton( onPressed: onPressed, style: ElevatedButton.styleFrom( shape: CircleBorder(), elevation: 0, backgroundColor: Theme.of(context).colorScheme.primary, padding: EdgeInsets.zero, minimumSize: const Size(0, 0), ), child: Icon(icon, color: Colors.white), ); }