117 lines
3.0 KiB
Dart
117 lines
3.0 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
/// 通用按钮(带 loading 态)
|
|
class LoadingButton extends StatelessWidget {
|
|
final String text;
|
|
final VoidCallback? onPressed;
|
|
final bool loading;
|
|
final Color? color;
|
|
final Color? textColor;
|
|
final double? width;
|
|
final double height;
|
|
final double radius;
|
|
|
|
const LoadingButton({
|
|
super.key,
|
|
required this.text,
|
|
this.onPressed,
|
|
this.loading = false,
|
|
this.color,
|
|
this.textColor,
|
|
this.width,
|
|
this.height = 48,
|
|
this.radius = 24,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final c = color ?? Theme.of(context).primaryColor;
|
|
final tc = textColor ?? Colors.white;
|
|
return SizedBox(
|
|
width: width,
|
|
height: height,
|
|
child: ElevatedButton(
|
|
onPressed: loading ? null : onPressed,
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: c,
|
|
foregroundColor: tc,
|
|
disabledBackgroundColor: c.withValues(alpha: 0.5),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(radius),
|
|
),
|
|
),
|
|
child: loading
|
|
? SizedBox(
|
|
width: 20,
|
|
height: 20,
|
|
child: CircularProgressIndicator(
|
|
strokeWidth: 2,
|
|
valueColor: AlwaysStoppedAnimation<Color>(tc),
|
|
),
|
|
)
|
|
: Text(
|
|
text,
|
|
style: TextStyle(fontSize: 16, color: tc, fontWeight: FontWeight.w600),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 通用 Section 头
|
|
class SectionHeader extends StatelessWidget {
|
|
final String title;
|
|
final String? actionText;
|
|
final VoidCallback? onAction;
|
|
final EdgeInsetsGeometry padding;
|
|
|
|
const SectionHeader({
|
|
super.key,
|
|
required this.title,
|
|
this.actionText,
|
|
this.onAction,
|
|
this.padding = const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Padding(
|
|
padding: padding,
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Text(title,
|
|
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600)),
|
|
if (actionText != null)
|
|
GestureDetector(
|
|
onTap: onAction,
|
|
child: Text(actionText!,
|
|
style: TextStyle(
|
|
fontSize: 13, color: Theme.of(context).primaryColor)),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 通用空状态
|
|
class EmptyView extends StatelessWidget {
|
|
final String text;
|
|
final IconData icon;
|
|
const EmptyView({super.key, this.text = '暂无数据', this.icon = Icons.inbox_outlined});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Center(
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Icon(icon, size: 64, color: Colors.grey.shade400),
|
|
const SizedBox(height: 8),
|
|
Text(text, style: TextStyle(color: Colors.grey.shade600)),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
} |