Xcode — 批量自定义按钮

在 SwiftUI 中,当你有一批按钮(Button)需要使用统一的样式,且不想每次都重复定义相同的修饰符代码时,可以通过以下几种方法来实现代码的复用和统一样式设置:


方法 1:创建自定义 View Modifier #

SwiftUI 提供了 ViewModifier,它允许你创建一个自定义的修饰符,用于集中定义按钮样式。这是最灵活的解决方案。

示例代码 #

  1. 创建一个自定义 View Modifier:
import SwiftUI

struct CustomButtonModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .padding() // 设置内边距
            .background(Color.blue) // 按钮背景颜色
            .cornerRadius(10) // 圆角
            .foregroundColor(.white) // 文字颜色
            .shadow(radius: 5) // 设置阴影
            .font(.headline) // 文字字体
    }
}
  1. 简化调用:通过扩展 View 添加一个简便方法:
extension View {
    func customButtonStyle() -> some View {
        self.modifier(CustomButtonModifier())
    }
}
  1. 在按钮中使用:
struct ContentView: View {
    var body: some View {
        VStack(spacing: 20) {
            Button("Primary") {
                print("Primary Button")
            }
            .customButtonStyle() // 使用自定义样式

            Button("Secondary") {
                print("Secondary Button")
            }
            .customButtonStyle() // 使用相同的样式
        }
    }
}

优点 #

  • 所有按钮样式可以在 CustomButtonModifier 中集中维护。
  • 如果需要更改样式,只需修改 CustomButtonModifier

方法 2:创建自定义的按钮 View #

如果样式非常固定,可以把按钮封装为一个自定义的组件,这样可以直接创建样式化的按钮。

示例代码 #

  1. 定义一个自定义按钮组件:
import SwiftUI

struct CustomButton: View {
    var title: String
    var action: () -> Void

    var body: some View {
        Button(action: action) {
            Text(title)
                .padding() // 设置内边距
                .background(Color.blue) // 按钮背景
                .foregroundColor(.white) // 文字颜色
                .cornerRadius(10) // 圆角
                .shadow(radius: 5) // 阴影
        }
    }
}
  1. 使用时直接调用组件:
struct ContentView: View {
    var body: some View {
        VStack(spacing: 20) {
            CustomButton(title: "Primary Button") {
                print("Primary Button clicked")
            }
            CustomButton(title: "Secondary Button") {
                print("Secondary Button clicked")
            }
        }
        .padding()
    }
}

优点 #

  • 不再需要每次调用样式修饰符,直接通过自定义组件即可复用。
  • 每个按钮都具有固定的外观,简化了代码结构。

方法 3:使用 Environment Values 共享样式 #

SwiftUI 提供了 Environment,可以用它来统一存储并共享样式。结合自定义样式和 Environment Key,就可以实现按钮样式的全局定义。

示例代码 #

  1. 定义一个 Environment Key:
import SwiftUI

struct ButtonStyleKey: EnvironmentKey {
    static let defaultValue: AnyViewModifier = AnyViewModifier(
        modifier: CustomButtonModifier()
    )
}

extension EnvironmentValues {
    var buttonStyle: AnyViewModifier {
        get { self[ButtonStyleKey.self] }
        set { self[ButtonStyleKey.self] = newValue }
    }
}
  1. 使用 Environment Key 在指定范围提供样式:
struct ContentView: View {
    @Environment(\.buttonStyle) var buttonStyle

    var body: some View {
        VStack(spacing: 20) {
            Button("Primary Button", action: {})
                .modifier(buttonStyle.modifier)
            Button("Secondary Button", action: {})
                .modifier(buttonStyle.modifier)
        }
        .environment(\.buttonStyle, AnyViewModifier(modifier: CustomButtonModifier()))
        .padding()
    }
}
  1. 自定义 AnyViewModifier 来封装所有样式:
struct AnyViewModifier: ViewModifier {
    let modifier: (Content) -> AnyView
    init<V: ViewModifier>(modifier: V) {
        self.modifier = { AnyView($0.modifier(modifier)) }
    }
    func body(content: Content) -> some View {
        modifier(content)
    }
}

方法 4:使用 SwiftUI 的 ButtonStyle 协议 #

SwiftUI 提供了内置的 ButtonStyle 协议,你可以通过自定义按钮样式来集中管理所有按钮外观。

示例代码 #

  1. 创建一个自定义按钮样式:
struct CustomButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .padding()
            .frame(maxWidth: .infinity) // 按钮宽度固定或适配父视图
            .background(configuration.isPressed ? Color.blue.opacity(0.6) : Color.blue) // 按下时效果
            .cornerRadius(10)
            .foregroundColor(.white)
            .shadow(radius: configuration.isPressed ? 0 : 5) // 按下时改变阴影
    }
}
  1. 在按钮中使用该自定义样式:
struct ContentView: View {
    var body: some View {
        VStack(spacing: 20) {
            Button("Primary Button") {
                print("Button 1")
            }
            .buttonStyle(CustomButtonStyle()) // 使用自定义按钮样式

            Button("Secondary Button") {
                print("Button 2")
            }
            .buttonStyle(CustomButtonStyle())
        }
        .padding()
    }
}
  1. 如果需要在全局范围内设置按钮样式,使用 .buttonStyle() 修饰父级容器:
struct ContentView: View {
    var body: some View {
        VStack(spacing: 20) {
            Button("Primary Button") { print("Primary Button Pressed") }
            Button("Secondary Button") { print("Secondary Button Pressed") }
        }
        .buttonStyle(CustomButtonStyle()) // 对所有子按钮生效
        .padding()
    }
}

推荐方案 #

  • 需要简单复用样式: 使用 自定义 View Modifier(方法 1)。
  • 需要封装自成组件: 使用 自定义按钮 View(方法 2)。
  • 需要全局统一样式: 使用 ButtonStyle 协议(方法 4) 或 Environment(方法 3)。
  • 组合样式和行为: 将按钮封装成自定义组件,便于样式和逻辑统一管理(方法 2 最推荐)。

这几种方法可以根据你的需求灵活选择!

本文共 1176 字,上次修改于 Feb 9, 2025
相关标签: Xcode