225 lines
6.1 KiB
Dart
225 lines
6.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_common/widget/dialog_widget.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),
|
|
);
|
|
}
|
|
|
|
// 底部弹出
|
|
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 showConfirmDialog(context, '确定要删除这个项目吗?');
|
|
},
|
|
onDismissed: (direction) {
|
|
onDelete();
|
|
},
|
|
child: child,
|
|
);
|
|
}
|
|
|
|
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,
|
|
}) {
|
|
final colors = Theme.of(context).colorScheme;
|
|
|
|
return ToggleSwitch(
|
|
minWidth: 90.0,
|
|
minHeight: 40.0,
|
|
initialLabelIndex: tabValues.indexOf(currentTab),
|
|
totalSwitches: tabValues.length,
|
|
labels: labels,
|
|
activeBgColor: [colors.primary],
|
|
activeFgColor: Colors.white,
|
|
inactiveBgColor: colors.surfaceContainer,
|
|
inactiveFgColor: colors.onSurface,
|
|
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<BorderSide>(
|
|
BorderSide(color: colors.surface, width: 0),
|
|
),
|
|
iconColor: WidgetStateProperty.resolveWith<Color>((
|
|
Set<WidgetState> states,
|
|
) {
|
|
if (states.contains(WidgetState.selected)) {
|
|
return colors.onPrimary;
|
|
}
|
|
return Colors.grey;
|
|
}),
|
|
backgroundColor: WidgetStateProperty.resolveWith<Color>((
|
|
Set<WidgetState> states,
|
|
) {
|
|
if (states.contains(WidgetState.selected)) {
|
|
return colors.primary;
|
|
}
|
|
return colors.surfaceContainer;
|
|
}),
|
|
foregroundColor: WidgetStateProperty.resolveWith<Color>((
|
|
Set<WidgetState> states,
|
|
) {
|
|
if (states.contains(WidgetState.selected)) {
|
|
return colors.onPrimary;
|
|
}
|
|
return colors.onSurface;
|
|
}),
|
|
shape: WidgetStateProperty.all<RoundedRectangleBorder>(
|
|
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),
|
|
);
|
|
}
|