import SwiftUI // 按钮类型 enum ButtonType { case primary // 主按钮(蓝色) case secondary // 次要按钮(灰色边框) case danger // 危险按钮(红色) } // 按钮大小(可选) enum ButtonSize { case small case medium case large } struct CustomButton: View { // MARK: - 属性 let text: String let type: ButtonType let size: ButtonSize let fullWidth: Bool // 是否占满父容器宽度 let isLoading: Bool // 是否加载中 let action: () -> Void // 点击回调(无参数) // MARK: - 主体视图 var body: some View { Button(action: { if !isLoading { // 防止加载时触发 action() } }) { if isLoading { // 显示加载动画 HStack { ProgressView() // iOS 加载指示器 .progressViewStyle(CircularProgressViewStyle(tint: .white)) Text("加载中...") } } else { Text(text) .fontWeight(.medium) } } .font(font(for: size)) .padding(padding(for: size)) .frame(maxWidth: fullWidth ? .infinity : (width(for: size))) .background(backgroundColor) .foregroundColor(.white) .cornerRadius(8) .overlay( // 次要按钮:只显示边框 RoundedRectangle(cornerRadius: 8) .stroke(borderColor, lineWidth: 2) .opacity(type == .secondary ? 1 : 0) ) .disabled(isLoading) // 加载时禁用点击 .opacity(isLoading ? 0.8 : 1.0) } // MARK: - 计算属性:背景色 private var backgroundColor: Color { switch type { case .primary: return .blue case .secondary: return .clear case .danger: return .red } } // MARK: - 计算属性:边框色 private var borderColor: Color { switch type { case .secondary: return .gray default: return .clear } } // MARK: - 辅助函数:字体 private func font(for size: ButtonSize) -> Font { switch size { case .small: return .caption case .medium: return .subheadline case .large: return .headline } } // MARK: - 辅助函数:内边距 private func padding(for size: ButtonSize) -> EdgeInsets { let horizontal = CGFloat(16) let vertical: CGFloat switch size { case .small: vertical = 6 case .medium: vertical = 10 case .large: vertical = 14 } return EdgeInsets(top: vertical, leading: horizontal, bottom: vertical, trailing: horizontal) } // MARK: - 辅助函数:固定宽度(非全宽时) private func width(for size: ButtonSize) -> CGFloat? { return nil // 自适应宽度,除非你想要固定值 } }