115 lines
3.0 KiB
Swift
115 lines
3.0 KiB
Swift
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 // 自适应宽度,除非你想要固定值
|
||
}
|
||
}
|