SwiftUI中的ViewModifier与View扩展

ViewModifier基础

ViewModifier是一个协议,用于封装可重用的视图修饰逻辑。

  • Name
    特点
    Type
    features
    Description
    • 可重用的视图修饰逻辑
    • 减少代码重复
    • 提高代码可维护性
    • 支持组合使用
  • Name
    使用场景
    Type
    usage
    Description
    • 统一的样式定义
    • 复杂的视图修饰组合
    • 需要重复使用的修饰逻辑

ViewModifier示例

struct PrimaryButtonStyle: ViewModifier {
    func body(content: Content) -> some View {
        content
            .padding()
            .background(Color.blue)
            .foregroundColor(.white)
            .cornerRadius(10)
            .shadow(radius: 5)
    }
}

// 使用方式
Button("点击我") {}
    .modifier(PrimaryButtonStyle())

View扩展方法

通过扩展View协议,可以将ViewModifier封装成更易用的方法。

  • Name
    特点
    Type
    features
    Description
    • 更简洁的调用语法
    • 支持参数自定义
    • 提高代码可读性
    • 便于维护和修改
  • Name
    使用场景
    Type
    usage
    Description
    • 简化ViewModifier的使用
    • 创建可复用的样式方法
    • 统一管理UI风格

View扩展示例

extension View {
    func primaryButton() -> some View {
        modifier(PrimaryButtonStyle())
    }
    
    func cardStyle(
        cornerRadius: CGFloat = 10,
        shadowRadius: CGFloat = 5
    ) -> some View {
        self
            .padding()
            .background(Color.white)
            .cornerRadius(cornerRadius)
            .shadow(radius: shadowRadius)
    }
}

// 使用方式
Button("登录") {}
    .primaryButton()

VStack {
    Text("卡片内容")
}
.cardStyle()

实战应用

结合ViewModifier和View扩展实现复杂的UI效果。

  • Name
    特点
    Type
    features
    Description
    • 组合多个修饰符
    • 支持动态参数
    • 复用度高
    • 代码更清晰
  • Name
    使用场景
    Type
    usage
    Description
    • 自定义导航栏样式
    • 统一的列表样式
    • 通用的动画效果

实战示例

struct ShakeEffect: ViewModifier {
    let amount: CGFloat
    let shakesPerSecond: Double
    @State private var isShaking = false
    
    func body(content: Content) -> some View {
        content
            .offset(x: isShaking ? amount : -amount)
            .animation(
                .linear(duration: 1/shakesPerSecond)
                .repeatForever(),
                value: isShaking
            )
            .onAppear { isShaking = true }
    }
}

extension View {
    func shake(
        amount: CGFloat = 5,
        shakesPerSecond: Double = 5
    ) -> some View {
        modifier(ShakeEffect(
            amount: amount,
            shakesPerSecond: shakesPerSecond
        ))
    }
}

// 使用示例
Text("输入错误!")
    .shake()

这篇文章对你有用吗?