215 lines
5.7 KiB
Dart
215 lines
5.7 KiB
Dart
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.surface,
|
|
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.surface,
|
|
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<bool?> showDeleteConfirmationDialog(BuildContext context) async {
|
|
return showDialog<bool>(
|
|
context: context,
|
|
builder: (BuildContext context) {
|
|
return AlertDialog(
|
|
title: const Text('确认删除'),
|
|
backgroundColor: Colors.white,
|
|
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<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]);
|
|
}
|
|
},
|
|
);
|
|
}
|