| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- import 'package:flutter/material.dart';
- import '../../theme/app_colors.dart';
- import '../../utils/constants.dart';
- /// 按钮类型
- enum ButtonType { primary, secondary, danger, text }
- /// 按钮尺寸
- enum ButtonSize { small, medium, large }
- /// 应用按钮组件
- class AppButton extends StatelessWidget {
- final String? text;
- final Widget? child;
- final VoidCallback? onPressed;
- final ButtonType type;
- final ButtonSize size;
- final bool loading;
- final IconData? icon;
- final bool fullWidth;
- const AppButton({
- Key? key,
- this.text,
- this.child,
- this.onPressed,
- this.type = ButtonType.primary,
- this.size = ButtonSize.medium,
- this.loading = false,
- this.icon,
- this.fullWidth = false,
- }) : assert(text != null || child != null, 'text or child must be provided'),
- super(key: key);
- @override
- Widget build(BuildContext context) {
- final content = child ?? Text(text!);
- final buttonContent = loading
- ? SizedBox(
- width: _getIconSize(),
- height: _getIconSize(),
- child: CircularProgressIndicator(
- strokeWidth: 2,
- valueColor: AlwaysStoppedAnimation<Color>(_getTextColor()),
- ),
- )
- : Row(
- mainAxisSize: fullWidth ? MainAxisSize.max : MainAxisSize.min,
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- if (icon != null) ...[
- Icon(icon, size: _getIconSize(), color: _getTextColor()),
- SizedBox(width: AppSpacing.sm),
- ],
- content,
- ],
- );
- final button = _buildButton(context, buttonContent);
- if (fullWidth) {
- return SizedBox(width: double.infinity, child: button);
- }
- return button;
- }
- Widget _buildButton(BuildContext context, Widget content) {
- switch (type) {
- case ButtonType.primary:
- return ElevatedButton(
- onPressed: loading ? null : onPressed,
- style: ElevatedButton.styleFrom(
- backgroundColor: AppColors.primary,
- foregroundColor: Colors.white,
- padding: _getPadding(),
- minimumSize: Size(0, _getHeight()),
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(6),
- ),
- ),
- child: content,
- );
- case ButtonType.secondary:
- return OutlinedButton(
- onPressed: loading ? null : onPressed,
- style: OutlinedButton.styleFrom(
- foregroundColor: AppColors.primary,
- padding: _getPadding(),
- minimumSize: Size(0, _getHeight()),
- side: const BorderSide(color: AppColors.primary),
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(6),
- ),
- ),
- child: content,
- );
- case ButtonType.danger:
- return ElevatedButton(
- onPressed: loading ? null : onPressed,
- style: ElevatedButton.styleFrom(
- backgroundColor: AppColors.error,
- foregroundColor: Colors.white,
- padding: _getPadding(),
- minimumSize: Size(0, _getHeight()),
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(6),
- ),
- ),
- child: content,
- );
- case ButtonType.text:
- return TextButton(
- onPressed: loading ? null : onPressed,
- style: TextButton.styleFrom(
- foregroundColor: AppColors.primary,
- padding: _getPadding(),
- minimumSize: Size(0, _getHeight()),
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(6),
- ),
- ),
- child: content,
- );
- }
- }
- EdgeInsets _getPadding() {
- switch (size) {
- case ButtonSize.small:
- return const EdgeInsets.symmetric(horizontal: 12, vertical: 6);
- case ButtonSize.medium:
- return const EdgeInsets.symmetric(horizontal: 24, vertical: 12);
- case ButtonSize.large:
- return const EdgeInsets.symmetric(horizontal: 32, vertical: 16);
- }
- }
- double _getHeight() {
- switch (size) {
- case ButtonSize.small:
- return 28;
- case ButtonSize.medium:
- return 40;
- case ButtonSize.large:
- return 48;
- }
- }
- double _getIconSize() {
- switch (size) {
- case ButtonSize.small:
- return 14;
- case ButtonSize.medium:
- return 18;
- case ButtonSize.large:
- return 20;
- }
- }
- Color _getTextColor() {
- switch (type) {
- case ButtonType.primary:
- case ButtonType.danger:
- return Colors.white;
- case ButtonType.secondary:
- case ButtonType.text:
- return AppColors.primary;
- }
- }
- }
|